From 8c2de64182b72463cb12f08fba7407ec6838f000 Mon Sep 17 00:00:00 2001 From: Pranav Gaikwad Date: Thu, 28 Sep 2023 14:54:43 -0400 Subject: [PATCH] :sparkles: add short-circuit filter label Signed-off-by: Pranav Gaikwad --- docs/labels.md | 11 ++++++----- engine/labels/labels.go | 16 ++++++++++++++++ engine/labels/labels_test.go | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/docs/labels.md b/docs/labels.md index 023dd357..3755ffa9 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: +Analyzer defines some labels that are commonly used to express known pieces of information about a rule: -- `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/selector`: Defines rule disposition with respect to the [rule label selector](#rule-label-selector). A value of `always` indicates that the rule will always be included irrespective of the label selector, while a value of `never` indicates that the rule will always be excluded. -## 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..048cecb3 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 + SelectorLabel = "konveyor.io/selector" + 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[SelectorLabel]; 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..1b0e7315 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/selector=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/selector=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) {