diff --git a/docs/labels.md b/docs/labels.md index 023dd357..661fbaf3 100644 --- a/docs/labels.md +++ b/docs/labels.md @@ -29,14 +29,15 @@ labels: - "konveyor.io/key" ``` -## Reserved Labels +## Rule Labels -The analyzer defines some labels that have special meaning. Here is a list of all such labels: +The analyzer defines some labels that have special meanings: -- `konveyor.io/source`: Identifies source technology a rule or a ruleset applies to. -- `konveyor.io/target`: Identifies target technology a rule or a ruleset applies to. +- `konveyor.io/source`: Identifies source technology a rule or a ruleset applies to. The value can be a string with optional version range at the end e.g. "eap", "eap6", "eap7-" etc. +- `konveyor.io/target`: Identifies target technology a rule or a ruleset applies to. The value can be a string with optional version range at the end e.g. "eap", "eap6", "eap8+" etc. +- `konveyor.io/include`: Overrides filter behavior for a rule irrespective of the label selector used. The value can either be `always` or `never`. `always` will always filter-in this rule, `never` will always filter-out this rule. -## Label Selector +### Rule Label Selector The analyzer CLI takes `--label-selector` as an option. It is a string expression that supports logical AND, OR and NOT operations. It can be used to filter-in/filter-out rules based on labels. diff --git a/engine/labels/labels.go b/engine/labels/labels.go index 68144a9f..44d5d37a 100644 --- a/engine/labels/labels.go +++ b/engine/labels/labels.go @@ -10,6 +10,13 @@ import ( "github.com/hashicorp/go-version" ) +const ( + // a selector label takes precedance over any other label when matching + RuleIncludeLabel = "konveyor.io/include" + SelectAlways = "always" + SelectNever = "never" +) + const ( LabelValueFmt = "^[a-zA-Z0-9]([-a-zA-Z0-9. ]*[a-zA-Z0-9+-])?$" LabelPrefixFmt = "^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" @@ -33,6 +40,15 @@ func AsString(key, value string) string { func (l *LabelSelector[T]) Matches(v T) (bool, error) { ruleLabels, _ := ParseLabels(v.GetLabels()) + if val, ok := ruleLabels[RuleIncludeLabel]; ok && + val != nil && len(val) > 0 { + switch val[0] { + case SelectAlways: + return true, nil + case SelectNever: + return false, nil + } + } expr := getBooleanExpression(l.expr, ruleLabels) val, err := l.language.Evaluate(expr, nil) if err != nil { diff --git a/engine/labels/labels_test.go b/engine/labels/labels_test.go index 697ee4d7..f8b212f8 100644 --- a/engine/labels/labels_test.go +++ b/engine/labels/labels_test.go @@ -360,6 +360,24 @@ func Test_ruleSelector_Matches(t *testing.T) { }, want: true, }, + { + name: "rule has a explicit selector=always label", + expr: "konveyor.io/source=test", + ruleLabels: []string{ + "konveyor.io/include=always", + "konveyor.io/source=noTest", // this should make the selector not match, but 'always' selector takes precedance + }, + want: true, + }, + { + name: "rule has a explicit selector=never label", + expr: "konveyor.io/source=test", + ruleLabels: []string{ + "konveyor.io/include=never", + "konveyor.io/source=test", // this should make the selector match, but 'never' selector takes precedance + }, + want: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {