diff --git a/apis/core.oam.dev/v1alpha1/garbagecollect_types.go b/apis/core.oam.dev/v1alpha1/garbagecollect_types.go index 90a59af84..53373d1b7 100644 --- a/apis/core.oam.dev/v1alpha1/garbagecollect_types.go +++ b/apis/core.oam.dev/v1alpha1/garbagecollect_types.go @@ -46,10 +46,11 @@ type GarbageCollectPolicyRule struct { // GarbageCollectPolicyRuleSelector select the targets of the rule // if both traitTypes and componentTypes are specified, combination logic is OR -// if one resources are specified with conflict strategy, strategy as component go first. +// if one resource is specified with conflict strategies, strategy as component go first. type GarbageCollectPolicyRuleSelector struct { - TraitTypes []string `json:"traitTypes"` + CompNames []string `json:"componentNames"` CompTypes []string `json:"componentTypes"` + TraitTypes []string `json:"traitTypes"` } // GarbageCollectStrategy the strategy for target resource to recycle @@ -68,27 +69,22 @@ const ( // FindStrategy find gc strategy for target resource func (in GarbageCollectPolicySpec) FindStrategy(manifest *unstructured.Unstructured) *GarbageCollectStrategy { for _, rule := range in.Rules { - var ( - compType string - traitType string - ) - if manifest.GetLabels() != nil { - traitType = manifest.GetLabels()[oam.TraitTypeLabel] - compType = manifest.GetLabels()[oam.WorkloadTypeLabel] + var compName, compType, traitType string + if labels := manifest.GetLabels(); labels != nil { + compName = labels[oam.LabelAppComponent] + compType = labels[oam.WorkloadTypeLabel] + traitType = labels[oam.TraitTypeLabel] } - if compType != "" { - for _, _compType := range rule.Selector.CompTypes { - if _compType == compType { - return &rule.Strategy - } + match := func(src []string, val string) (found bool) { + for _, _val := range src { + found = found || _val == val } + return val != "" && found } - if traitType != "" { - for _, _traitType := range rule.Selector.TraitTypes { - if _traitType == traitType { - return &rule.Strategy - } - } + if match(rule.Selector.CompNames, compName) || + match(rule.Selector.CompTypes, compType) || + match(rule.Selector.TraitTypes, traitType) { + return &rule.Strategy } } return nil diff --git a/apis/core.oam.dev/v1alpha1/garbagecollect_types_test.go b/apis/core.oam.dev/v1alpha1/garbagecollect_types_test.go index 390c177ff..5e4dfd9e3 100644 --- a/apis/core.oam.dev/v1alpha1/garbagecollect_types_test.go +++ b/apis/core.oam.dev/v1alpha1/garbagecollect_types_test.go @@ -32,7 +32,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { notFound bool expectStrategy GarbageCollectStrategy }{ - "trait rule match": { + "trait type rule match": { rules: []GarbageCollectPolicyRule{{ Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}}, Strategy: GarbageCollectStrategyNever, @@ -44,7 +44,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { }}, expectStrategy: GarbageCollectStrategyNever, }, - "trait rule mismatch": { + "trait type rule mismatch": { rules: []GarbageCollectPolicyRule{{ Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}}, Strategy: GarbageCollectStrategyNever, @@ -52,7 +52,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { input: &unstructured.Unstructured{Object: map[string]interface{}{}}, notFound: true, }, - "trait rule multiple match": { + "trait type rule multiple match": { rules: []GarbageCollectPolicyRule{{ Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}}, Strategy: GarbageCollectStrategyOnAppDelete, @@ -67,7 +67,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { }}, expectStrategy: GarbageCollectStrategyOnAppDelete, }, - "component rule match": { + "component type rule match": { rules: []GarbageCollectPolicyRule{{ Selector: GarbageCollectPolicyRuleSelector{CompTypes: []string{"comp"}}, Strategy: GarbageCollectStrategyNever, @@ -79,7 +79,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { }}, expectStrategy: GarbageCollectStrategyNever, }, - "rule match both component and trait, component first": { + "rule match both component type and trait type, component type first": { rules: []GarbageCollectPolicyRule{ { Selector: GarbageCollectPolicyRuleSelector{CompTypes: []string{"comp"}}, @@ -97,6 +97,18 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) { }}, expectStrategy: GarbageCollectStrategyNever, }, + "component name rule match": { + rules: []GarbageCollectPolicyRule{{ + Selector: GarbageCollectPolicyRuleSelector{CompNames: []string{"comp-name"}}, + Strategy: GarbageCollectStrategyNever, + }}, + input: &unstructured.Unstructured{Object: map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": map[string]interface{}{oam.LabelAppComponent: "comp-name"}, + }, + }}, + expectStrategy: GarbageCollectStrategyNever, + }, } for name, tc := range testCases { t.Run(name, func(t *testing.T) { diff --git a/apis/core.oam.dev/v1alpha1/zz_generated.deepcopy.go b/apis/core.oam.dev/v1alpha1/zz_generated.deepcopy.go index a5f3e27e7..517295c47 100644 --- a/apis/core.oam.dev/v1alpha1/zz_generated.deepcopy.go +++ b/apis/core.oam.dev/v1alpha1/zz_generated.deepcopy.go @@ -281,8 +281,8 @@ func (in *GarbageCollectPolicyRule) DeepCopy() *GarbageCollectPolicyRule { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GarbageCollectPolicyRuleSelector) DeepCopyInto(out *GarbageCollectPolicyRuleSelector) { *out = *in - if in.TraitTypes != nil { - in, out := &in.TraitTypes, &out.TraitTypes + if in.CompNames != nil { + in, out := &in.CompNames, &out.CompNames *out = make([]string, len(*in)) copy(*out, *in) } @@ -291,6 +291,11 @@ func (in *GarbageCollectPolicyRuleSelector) DeepCopyInto(out *GarbageCollectPoli *out = make([]string, len(*in)) copy(*out, *in) } + if in.TraitTypes != nil { + in, out := &in.TraitTypes, &out.TraitTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectPolicyRuleSelector. diff --git a/docs/examples/app-with-policy/gc-policy/persist-resources.md b/docs/examples/app-with-policy/gc-policy/persist-resources.md index 9195309bf..323ea284c 100644 --- a/docs/examples/app-with-policy/gc-policy/persist-resources.md +++ b/docs/examples/app-with-policy/gc-policy/persist-resources.md @@ -95,7 +95,32 @@ spec: properties: rules: - selector: - componentTypes: - - webservice - strategy: never + componentTypes: + - webservice + strategy: never +``` + +A more straightforward way is to specify `compNames` to match specified components. +```yaml +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: create-ns-app +spec: + components: + - name: example-addon-namespace + type: k8s-objects + properties: + objects: + - apiVersion: v1 + kind: Namespace + policies: + - name: garbage-collect + type: garbage-collect + properties: + rules: + - selector: + componentNames: + - example-addon-namespace + strategy: never ```