diff --git a/apis/core.oam.dev/v1alpha1/applyonce_types.go b/apis/core.oam.dev/v1alpha1/applyonce_types.go index 033d5d449..d713c18dc 100644 --- a/apis/core.oam.dev/v1alpha1/applyonce_types.go +++ b/apis/core.oam.dev/v1alpha1/applyonce_types.go @@ -53,15 +53,7 @@ func (in ApplyOncePolicySpec) FindStrategy(manifest *unstructured.Unstructured) return nil } for _, rule := range in.Rules { - match := func(src []string, val string) (found bool) { - for _, _val := range src { - found = found || _val == val - } - return val != "" && found - } - if (match(rule.Selector.CompNames, manifest.GetName()) && match(rule.Selector.ResourceTypes, manifest.GetKind())) || - (rule.Selector.CompNames == nil && match(rule.Selector.ResourceTypes, manifest.GetKind()) || - (rule.Selector.ResourceTypes == nil && match(rule.Selector.CompNames, manifest.GetName()))) { + if rule.Selector.Match(manifest) { return rule.Strategy } } diff --git a/apis/core.oam.dev/v1alpha1/garbagecollect_types.go b/apis/core.oam.dev/v1alpha1/garbagecollect_types.go index c0e38cefa..9924d396b 100644 --- a/apis/core.oam.dev/v1alpha1/garbagecollect_types.go +++ b/apis/core.oam.dev/v1alpha1/garbagecollect_types.go @@ -18,6 +18,7 @@ package v1alpha1 import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/utils/pointer" "k8s.io/utils/strings/slices" "github.com/oam-dev/kubevela/pkg/oam" @@ -57,10 +58,7 @@ type GarbageCollectPolicyRule struct { } // ResourcePolicyRuleSelector select the targets of the rule -// 1) for GarbageCollectPolicyRule -// if both traitTypes, oamTypes and componentTypes are specified, combination logic is OR -// if one resource is specified with conflict strategies, strategy as component go first. -// 2) for ApplyOncePolicyRule only CompNames and ResourceTypes are used +// if multiple conditions are specified, combination logic is AND type ResourcePolicyRuleSelector struct { CompNames []string `json:"componentNames,omitempty"` CompTypes []string `json:"componentTypes,omitempty"` @@ -71,6 +69,8 @@ type ResourcePolicyRuleSelector struct { } // Match check if current rule selector match the target resource +// If at least one condition is matched and no other condition failed (could be empty), return true +// Otherwise, return false func (in *ResourcePolicyRuleSelector) Match(manifest *unstructured.Unstructured) bool { var compName, compType, oamType, traitType, resourceType, resourceName string if labels := manifest.GetLabels(); labels != nil { @@ -81,15 +81,33 @@ func (in *ResourcePolicyRuleSelector) Match(manifest *unstructured.Unstructured) } resourceType = manifest.GetKind() resourceName = manifest.GetName() - match := func(src []string, val string) (found bool) { - return val != "" && slices.Contains(src, val) + match := func(src []string, val string) (found *bool) { + if len(src) == 0 { + return nil + } + return pointer.Bool(val != "" && slices.Contains(src, val)) } - return match(in.CompNames, compName) || - match(in.CompTypes, compType) || - match(in.OAMResourceTypes, oamType) || - match(in.TraitTypes, traitType) || - match(in.ResourceTypes, resourceType) || - match(in.ResourceNames, resourceName) + conditions := []*bool{ + match(in.CompNames, compName), + match(in.CompTypes, compType), + match(in.OAMResourceTypes, oamType), + match(in.TraitTypes, traitType), + match(in.ResourceTypes, resourceType), + match(in.ResourceNames, resourceName), + } + hasMatched := false + for _, cond := range conditions { + // if any non-empty condition failed, return false + if cond != nil && !*cond { + return false + } + // if condition succeed, record it + if cond != nil && *cond { + hasMatched = true + } + } + // if at least one condition is met, return true + return hasMatched } // GarbageCollectStrategy the strategy for target resource to recycle diff --git a/pkg/resourcekeeper/statekeep_suite_test.go b/pkg/resourcekeeper/statekeep_suite_test.go index 2b08f68bb..e6a453254 100644 --- a/pkg/resourcekeeper/statekeep_suite_test.go +++ b/pkg/resourcekeeper/statekeep_suite_test.go @@ -276,6 +276,7 @@ var _ = Describe("Test ResourceKeeper StateKeep", func() { "metadata": map[string]interface{}{ "name": name, "namespace": "default", + "labels": map[string]interface{}{oam.LabelAppComponent: name}, }, "spec": map[string]interface{}{ "replicas": value,