mirror of https://github.com/kubevela/kubevela.git
Feat: support custom cascading gc policy (#6059)
This commit is contained in:
parent
e215b18a3e
commit
1a6dafafde
|
@ -80,12 +80,6 @@ jobs:
|
||||||
go install github.com/onsi/ginkgo/v2/ginkgo
|
go install github.com/onsi/ginkgo/v2/ginkgo
|
||||||
go get github.com/onsi/gomega/...
|
go get github.com/onsi/gomega/...
|
||||||
|
|
||||||
- name: Setup KinD
|
|
||||||
run: |
|
|
||||||
go install sigs.k8s.io/kind@v0.19.0
|
|
||||||
kind delete cluster --name kind || true
|
|
||||||
kind create cluster --name kind --image=kindest/node:v1.26.4
|
|
||||||
|
|
||||||
- name: Load image
|
- name: Load image
|
||||||
run: |
|
run: |
|
||||||
mkdir -p $HOME/tmp/
|
mkdir -p $HOME/tmp/
|
||||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -58,6 +60,7 @@ const (
|
||||||
type GarbageCollectPolicyRule struct {
|
type GarbageCollectPolicyRule struct {
|
||||||
Selector ResourcePolicyRuleSelector `json:"selector"`
|
Selector ResourcePolicyRuleSelector `json:"selector"`
|
||||||
Strategy GarbageCollectStrategy `json:"strategy"`
|
Strategy GarbageCollectStrategy `json:"strategy"`
|
||||||
|
Propagation *GarbageCollectPropagation `json:"propagation"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GarbageCollectStrategy the strategy for target resource to recycle
|
// GarbageCollectStrategy the strategy for target resource to recycle
|
||||||
|
@ -73,6 +76,16 @@ const (
|
||||||
GarbageCollectStrategyOnAppUpdate GarbageCollectStrategy = "onAppUpdate"
|
GarbageCollectStrategyOnAppUpdate GarbageCollectStrategy = "onAppUpdate"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GarbageCollectPropagation the deletion propagation setting similar to metav1.DeletionPropagation
|
||||||
|
type GarbageCollectPropagation string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GarbageCollectPropagationOrphan orphan child resources while deleting target resources
|
||||||
|
GarbageCollectPropagationOrphan = "orphan"
|
||||||
|
// GarbageCollectPropagationCascading delete child resources in background while deleting target resources
|
||||||
|
GarbageCollectPropagationCascading = "cascading"
|
||||||
|
)
|
||||||
|
|
||||||
// Type the type name of the policy
|
// Type the type name of the policy
|
||||||
func (in *GarbageCollectPolicySpec) Type() string {
|
func (in *GarbageCollectPolicySpec) Type() string {
|
||||||
return GarbageCollectPolicyType
|
return GarbageCollectPolicyType
|
||||||
|
@ -87,3 +100,18 @@ func (in *GarbageCollectPolicySpec) FindStrategy(manifest *unstructured.Unstruct
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindDeleteOption find delete option for target resource
|
||||||
|
func (in *GarbageCollectPolicySpec) FindDeleteOption(manifest *unstructured.Unstructured) []client.DeleteOption {
|
||||||
|
for _, rule := range in.Rules {
|
||||||
|
if rule.Selector.Match(manifest) && rule.Propagation != nil {
|
||||||
|
switch *rule.Propagation {
|
||||||
|
case GarbageCollectPropagationOrphan:
|
||||||
|
return []client.DeleteOption{client.PropagationPolicy(metav1.DeletePropagationOrphan)}
|
||||||
|
case GarbageCollectPropagationCascading:
|
||||||
|
return []client.DeleteOption{client.PropagationPolicy(metav1.DeletePropagationBackground)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -314,6 +314,11 @@ func (in *EnvTraitPatch) DeepCopy() *EnvTraitPatch {
|
||||||
func (in *GarbageCollectPolicyRule) DeepCopyInto(out *GarbageCollectPolicyRule) {
|
func (in *GarbageCollectPolicyRule) DeepCopyInto(out *GarbageCollectPolicyRule) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Selector.DeepCopyInto(&out.Selector)
|
in.Selector.DeepCopyInto(&out.Selector)
|
||||||
|
if in.Propagation != nil {
|
||||||
|
in, out := &in.Propagation, &out.Propagation
|
||||||
|
*out = new(GarbageCollectPropagation)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectPolicyRule.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectPolicyRule.
|
||||||
|
|
|
@ -16,6 +16,8 @@ spec:
|
||||||
selector: #ResourcePolicyRuleSelector
|
selector: #ResourcePolicyRuleSelector
|
||||||
// +usage=Specify the strategy for target resource to recycle
|
// +usage=Specify the strategy for target resource to recycle
|
||||||
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
||||||
|
// +usage=Specify the deletion propagation strategy for target resource to delete
|
||||||
|
propagation?: "orphan" | "cascading"
|
||||||
}
|
}
|
||||||
|
|
||||||
#ResourcePolicyRuleSelector: {
|
#ResourcePolicyRuleSelector: {
|
||||||
|
|
|
@ -43,6 +43,7 @@ import (
|
||||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||||
"github.com/oam-dev/kubevela/pkg/oam"
|
"github.com/oam-dev/kubevela/pkg/oam"
|
||||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||||
|
"github.com/oam-dev/kubevela/pkg/policy"
|
||||||
"github.com/oam-dev/kubevela/pkg/resourcetracker"
|
"github.com/oam-dev/kubevela/pkg/resourcetracker"
|
||||||
"github.com/oam-dev/kubevela/pkg/utils"
|
"github.com/oam-dev/kubevela/pkg/utils"
|
||||||
"github.com/oam-dev/kubevela/pkg/utils/apply"
|
"github.com/oam-dev/kubevela/pkg/utils/apply"
|
||||||
|
@ -405,7 +406,11 @@ func DeleteManagedResourceInApplication(ctx context.Context, cli client.Client,
|
||||||
}
|
}
|
||||||
return errors.Wrapf(cli.Update(_ctx, obj), "failed to remove owner labels for resource while skipping gc")
|
return errors.Wrapf(cli.Update(_ctx, obj), "failed to remove owner labels for resource while skipping gc")
|
||||||
}
|
}
|
||||||
if err := cli.Delete(_ctx, obj); err != nil && !kerrors.IsNotFound(err) {
|
var opts []client.DeleteOption
|
||||||
|
if garbageCollectPolicy, _ := policy.ParsePolicy[v1alpha1.GarbageCollectPolicySpec](app); garbageCollectPolicy != nil {
|
||||||
|
opts = garbageCollectPolicy.FindDeleteOption(obj)
|
||||||
|
}
|
||||||
|
if err := cli.Delete(_ctx, obj, opts...); err != nil && !kerrors.IsNotFound(err) {
|
||||||
return errors.Wrapf(err, "failed to delete resource %s", mr.ResourceKey())
|
return errors.Wrapf(err, "failed to delete resource %s", mr.ResourceKey())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1304,5 +1304,37 @@ var _ = Describe("Test multicluster scenario", func() {
|
||||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "fake-app"}, _fapp)).Should(Succeed())
|
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "fake-app"}, _fapp)).Should(Succeed())
|
||||||
Expect(string(_fapp.Status.Phase)).Should(Equal("unknown"))
|
Expect(string(_fapp.Status.Phase)).Should(Equal("unknown"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Test application with garbage-collect propagation setting", func() {
|
||||||
|
ctx := context.Background()
|
||||||
|
app := &v1beta1.Application{}
|
||||||
|
bs, err := os.ReadFile("./testdata/app/app-with-custom-gc-propagation.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("Deleting")
|
||||||
|
_app := &v1beta1.Application{}
|
||||||
|
Expect(k8sClient.Get(ctx, appKey, _app)).Should(Succeed())
|
||||||
|
Expect(k8sClient.Delete(ctx, _app)).Should(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
_app := &v1beta1.Application{}
|
||||||
|
g.Expect(kerrors.IsNotFound(k8sClient.Get(ctx, appKey, _app))).Should(BeTrue())
|
||||||
|
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
pods := &corev1.PodList{}
|
||||||
|
g.Expect(k8sClient.List(ctx, pods, client.InNamespace(namespace))).Should(Succeed())
|
||||||
|
g.Expect(len(pods.Items)).Should(Equal(1))
|
||||||
|
g.Expect(pods.Items[0].Name).Should(ContainSubstring("orphan"))
|
||||||
|
}).WithPolling(2 * time.Second).WithTimeout(20 * time.Second).Should(Succeed())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
apiVersion: core.oam.dev/v1beta1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: gc-propagation
|
||||||
|
spec:
|
||||||
|
components:
|
||||||
|
- type: webservice
|
||||||
|
name: orphan-gc
|
||||||
|
properties:
|
||||||
|
image: busybox
|
||||||
|
cmd:
|
||||||
|
- sleep
|
||||||
|
- '1000000'
|
||||||
|
- type: k8s-objects
|
||||||
|
name: cascading-gc
|
||||||
|
properties:
|
||||||
|
objects:
|
||||||
|
- apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pi
|
||||||
|
image: perl:5.34.0
|
||||||
|
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||||
|
restartPolicy: Never
|
||||||
|
backoffLimit: 4
|
||||||
|
policies:
|
||||||
|
- type: garbage-collect
|
||||||
|
properties:
|
||||||
|
rules:
|
||||||
|
- selector:
|
||||||
|
componentNames: ["orphan-gc"]
|
||||||
|
propagation: orphan
|
||||||
|
- selector:
|
||||||
|
componentNames: ["cascading-gc"]
|
||||||
|
propagation: cascading
|
|
@ -12,6 +12,8 @@ template: {
|
||||||
selector: #ResourcePolicyRuleSelector
|
selector: #ResourcePolicyRuleSelector
|
||||||
// +usage=Specify the strategy for target resource to recycle
|
// +usage=Specify the strategy for target resource to recycle
|
||||||
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
strategy: *"onAppUpdate" | "onAppDelete" | "never"
|
||||||
|
// +usage=Specify the deletion propagation strategy for target resource to delete
|
||||||
|
propagation?: "orphan" | "cascading"
|
||||||
}
|
}
|
||||||
|
|
||||||
#ResourcePolicyRuleSelector: {
|
#ResourcePolicyRuleSelector: {
|
||||||
|
|
Loading…
Reference in New Issue