mirror of https://github.com/kubevela/kubevela.git
Feat: support customizing application revision limit number in policy (#5995)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
parent
1af82cd282
commit
da8588c887
|
@ -27,6 +27,10 @@ const (
|
|||
|
||||
// GarbageCollectPolicySpec defines the spec of configuration drift
|
||||
type GarbageCollectPolicySpec struct {
|
||||
// ApplicationRevisionLimit if set, this application will use this number for application revision instead of
|
||||
// the global configuration
|
||||
ApplicationRevisionLimit *int `json:"applicationRevisionLimit,omitempty"`
|
||||
|
||||
// KeepLegacyResource if is set, outdated versioned resourcetracker will not be recycled automatically
|
||||
// outdated resources will be kept until resourcetracker be deleted manually
|
||||
KeepLegacyResource bool `json:"keepLegacyResource,omitempty"`
|
||||
|
|
|
@ -329,6 +329,11 @@ func (in *GarbageCollectPolicyRule) DeepCopy() *GarbageCollectPolicyRule {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GarbageCollectPolicySpec) DeepCopyInto(out *GarbageCollectPolicySpec) {
|
||||
*out = *in
|
||||
if in.ApplicationRevisionLimit != nil {
|
||||
in, out := &in.ApplicationRevisionLimit, &out.ApplicationRevisionLimit
|
||||
*out = new(int)
|
||||
**out = **in
|
||||
}
|
||||
if in.Rules != nil {
|
||||
in, out := &in.Rules, &out.Rules
|
||||
*out = make([]GarbageCollectPolicyRule, len(*in))
|
||||
|
|
|
@ -34,6 +34,8 @@ spec:
|
|||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=If set, it will override the default revision limit number and customize this number for the current application
|
||||
applicationRevisionLimit?: int
|
||||
// +usage=If is set, outdated versioned resourcetracker will not be recycled automatically, outdated resources will be kept until resourcetracker be deleted manually
|
||||
keepLegacyResource: *false | bool
|
||||
// +usage=If is set, continue to execute gc when the workflow fails, by default gc will be executed only after the workflow succeeds
|
||||
|
|
|
@ -901,6 +901,18 @@ func (h *AppHandler) UpdateAppLatestRevisionStatus(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getApplicationRevisionLimitForApp(app *v1beta1.Application, fallback int) int {
|
||||
for _, p := range app.Spec.Policies {
|
||||
if p.Type == v1alpha1.GarbageCollectPolicyType && p.Properties != nil && p.Properties.Raw != nil {
|
||||
prop := &v1alpha1.GarbageCollectPolicySpec{}
|
||||
if err := json.Unmarshal(p.Properties.Raw, prop); err == nil && prop.ApplicationRevisionLimit != nil && *prop.ApplicationRevisionLimit >= 0 {
|
||||
return *prop.ApplicationRevisionLimit
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
// cleanUpApplicationRevision check all appRevisions of the application, remove them if the number of them exceed the limit
|
||||
func cleanUpApplicationRevision(ctx context.Context, h *AppHandler) error {
|
||||
if DisableAllApplicationRevision {
|
||||
|
@ -915,11 +927,12 @@ func cleanUpApplicationRevision(ctx context.Context, h *AppHandler) error {
|
|||
return err
|
||||
}
|
||||
appRevisionInUse := gatherUsingAppRevision(h)
|
||||
needKill := len(sortedRevision) - h.r.appRevisionLimit - len(appRevisionInUse)
|
||||
appRevisionLimit := getApplicationRevisionLimitForApp(h.app, h.r.appRevisionLimit)
|
||||
needKill := len(sortedRevision) - appRevisionLimit - len(appRevisionInUse)
|
||||
if needKill <= 0 {
|
||||
return nil
|
||||
}
|
||||
klog.InfoS("Going to garbage collect app revisions", "limit", h.r.appRevisionLimit,
|
||||
klog.InfoS("Going to garbage collect app revisions", "limit", appRevisionLimit,
|
||||
"total", len(sortedRevision), "using", len(appRevisionInUse), "kill", needKill)
|
||||
|
||||
for _, rev := range sortedRevision {
|
||||
|
|
|
@ -1111,5 +1111,60 @@ var _ = Describe("Test multicluster scenario", func() {
|
|||
Expect(k8sClient.Get(workerCtx, appKey, _deploy)).Should(Succeed())
|
||||
Expect(int(*_deploy.Spec.Replicas)).Should(Equal(0))
|
||||
})
|
||||
|
||||
It("Test application with customized application revision limit", func() {
|
||||
ctx := context.Background()
|
||||
app := &v1beta1.Application{}
|
||||
bs, err := os.ReadFile("./testdata/app/app-lite.yaml")
|
||||
Expect(err).Should(Succeed())
|
||||
Expect(yaml.Unmarshal(bs, app)).Should(Succeed())
|
||||
app.SetNamespace(namespace)
|
||||
Eventually(func(g Gomega) {
|
||||
g.Expect(k8sClient.Create(ctx, app)).Should(Succeed())
|
||||
}).WithPolling(2 * time.Second).WithTimeout(5 * time.Second).Should(Succeed())
|
||||
appKey := client.ObjectKeyFromObject(app)
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||
g.Expect(_app.Status.Phase).Should(Equal(common.ApplicationRunning))
|
||||
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||
|
||||
By("update app and should have two revisions")
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||
_app.Spec.Components[0].Name = "dw"
|
||||
g.Expect(k8sClient.Update(ctx, _app)).Should(Succeed())
|
||||
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||
g.Expect(_app.Status.Phase).Should(Equal(common.ApplicationRunning))
|
||||
_revs := &v1beta1.ApplicationRevisionList{}
|
||||
g.Expect(k8sClient.List(ctx, _revs, client.InNamespace(namespace))).Should(Succeed())
|
||||
g.Expect(len(_revs.Items)).Should(Equal(2))
|
||||
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||
|
||||
By("update app with gc policy and should have one revision")
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||
_app.Spec.Components[0].Name = "dw2"
|
||||
_app.Spec.Policies = []v1beta1.AppPolicy{{
|
||||
Type: "garbage-collect",
|
||||
Name: "gc",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"applicationRevisionLimit":0}`)},
|
||||
}}
|
||||
g.Expect(k8sClient.Update(ctx, _app)).Should(Succeed())
|
||||
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||
Eventually(func(g Gomega) {
|
||||
_app := &v1beta1.Application{}
|
||||
g.Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||
g.Expect(_app.Status.Phase).Should(Equal(common.ApplicationRunning))
|
||||
_revs := &v1beta1.ApplicationRevisionList{}
|
||||
g.Expect(k8sClient.List(ctx, _revs, client.InNamespace(namespace))).Should(Succeed())
|
||||
g.Expect(len(_revs.Items)).Should(Equal(1))
|
||||
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: example-lite-app
|
||||
spec:
|
||||
components:
|
||||
- name: data-worker
|
||||
type: worker
|
||||
properties:
|
||||
image: busybox
|
||||
cmd:
|
||||
- sleep
|
||||
- '1000000'
|
|
@ -30,6 +30,8 @@ template: {
|
|||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=If set, it will override the default revision limit number and customize this number for the current application
|
||||
applicationRevisionLimit?: int
|
||||
// +usage=If is set, outdated versioned resourcetracker will not be recycled automatically, outdated resources will be kept until resourcetracker be deleted manually
|
||||
keepLegacyResource: *false | bool
|
||||
// +usage=If is set, continue to execute gc when the workflow fails, by default gc will be executed only after the workflow succeeds
|
||||
|
|
Loading…
Reference in New Issue