mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2024-12-14 11:57:51 +00:00
source/custom: move rule matching to pkg/apis/nfd
Move the rule processing of matchFeatures and matchAny from source/custom package over to pkg/apis/nfd, aiming for better integrity and re-usability of the code. Does not change the CRD API as such, just adds more supportive functions.
This commit is contained in:
parent
55ea049ed7
commit
8b9df3cf31
3 changed files with 136 additions and 139 deletions
100
pkg/apis/nfd/v1alpha1/rule.go
Normal file
100
pkg/apis/nfd/v1alpha1/rule.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"sigs.k8s.io/node-feature-discovery/pkg/api/feature"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Execute the rule against a set of input features.
|
||||||
|
func (r *Rule) Execute(features map[string]*feature.DomainFeatures) (map[string]string, error) {
|
||||||
|
if len(r.MatchAny) > 0 {
|
||||||
|
// Logical OR over the matchAny matchers
|
||||||
|
matched := false
|
||||||
|
for _, matcher := range r.MatchAny {
|
||||||
|
if m, err := matcher.match(features); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if m {
|
||||||
|
matched = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r.MatchFeatures) > 0 {
|
||||||
|
if m, err := r.MatchFeatures.match(features); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !m {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make(map[string]string, len(r.Labels))
|
||||||
|
for k, v := range r.Labels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MatchAnyElem) match(features map[string]*feature.DomainFeatures) (bool, error) {
|
||||||
|
return e.MatchFeatures.match(features)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FeatureMatcher) match(features map[string]*feature.DomainFeatures) (bool, error) {
|
||||||
|
// Logical AND over the terms
|
||||||
|
for _, term := range *m {
|
||||||
|
split := strings.SplitN(term.Feature, ".", 2)
|
||||||
|
if len(split) != 2 {
|
||||||
|
return false, fmt.Errorf("invalid selector %q: must be <domain>.<feature>", term.Feature)
|
||||||
|
}
|
||||||
|
domain := split[0]
|
||||||
|
// Ignore case
|
||||||
|
featureName := strings.ToLower(split[1])
|
||||||
|
|
||||||
|
domainFeatures, ok := features[domain]
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("unknown feature source/domain %q", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
var m bool
|
||||||
|
var err error
|
||||||
|
if f, ok := domainFeatures.Keys[featureName]; ok {
|
||||||
|
m, err = term.MatchExpressions.MatchKeys(f.Elements)
|
||||||
|
} else if f, ok := domainFeatures.Values[featureName]; ok {
|
||||||
|
m, err = term.MatchExpressions.MatchValues(f.Elements)
|
||||||
|
} else if f, ok := domainFeatures.Instances[featureName]; ok {
|
||||||
|
m, err = term.MatchExpressions.MatchInstances(f.Elements)
|
||||||
|
} else {
|
||||||
|
return false, fmt.Errorf("%q feature of source/domain %q not available", featureName, domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !m {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
|
@ -14,14 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package custom
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/node-feature-discovery/pkg/api/feature"
|
"sigs.k8s.io/node-feature-discovery/pkg/api/feature"
|
||||||
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRule(t *testing.T) {
|
func TestRule(t *testing.T) {
|
||||||
|
@ -32,32 +31,30 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.kf-1",
|
Feature: "domain-1.kf-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"key-1": MustCreateMatchExpression(MatchExists)},
|
||||||
"key-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchExists),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test totally empty features
|
// Test totally empty features
|
||||||
m, err := r1.execute(f)
|
m, err := r1.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
||||||
|
|
||||||
_, err = r2.execute(f)
|
_, err = r2.Execute(f)
|
||||||
assert.Error(t, err, "matching agains a missing domain should have returned an error")
|
assert.Error(t, err, "matching agains a missing domain should have returned an error")
|
||||||
|
|
||||||
// Test empty domain
|
// Test empty domain
|
||||||
d := feature.NewDomainFeatures()
|
d := feature.NewDomainFeatures()
|
||||||
f["domain-1"] = d
|
f["domain-1"] = d
|
||||||
|
|
||||||
m, err = r1.execute(f)
|
m, err = r1.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
||||||
|
|
||||||
_, err = r2.execute(f)
|
_, err = r2.Execute(f)
|
||||||
assert.Error(t, err, "matching agains a missing feature type should have returned an error")
|
assert.Error(t, err, "matching agains a missing feature type should have returned an error")
|
||||||
|
|
||||||
// Test empty feature sets
|
// Test empty feature sets
|
||||||
|
@ -65,11 +62,11 @@ func TestRule(t *testing.T) {
|
||||||
d.Values["vf-1"] = feature.NewValueFeatures(nil)
|
d.Values["vf-1"] = feature.NewValueFeatures(nil)
|
||||||
d.Instances["if-1"] = feature.NewInstanceFeatures(nil)
|
d.Instances["if-1"] = feature.NewInstanceFeatures(nil)
|
||||||
|
|
||||||
m, err = r1.execute(f)
|
m, err = r1.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
||||||
|
|
||||||
m, err = r2.execute(f)
|
m, err = r2.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "unexpected match")
|
assert.Nil(t, m, "unexpected match")
|
||||||
|
|
||||||
|
@ -79,17 +76,17 @@ func TestRule(t *testing.T) {
|
||||||
d.Instances["if-1"] = feature.NewInstanceFeatures([]feature.InstanceFeature{
|
d.Instances["if-1"] = feature.NewInstanceFeatures([]feature.InstanceFeature{
|
||||||
*feature.NewInstanceFeature(map[string]string{"attr-1": "val-x"})})
|
*feature.NewInstanceFeature(map[string]string{"attr-1": "val-x"})})
|
||||||
|
|
||||||
m, err = r1.execute(f)
|
m, err = r1.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
assert.Equal(t, r1.Labels, m, "empty matcher should have matched empty features")
|
||||||
|
|
||||||
// Match "key" features
|
// Match "key" features
|
||||||
m, err = r2.execute(f)
|
m, err = r2.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "keys should not have matched")
|
assert.Nil(t, m, "keys should not have matched")
|
||||||
|
|
||||||
d.Keys["kf-1"].Elements["key-1"] = feature.Nil{}
|
d.Keys["kf-1"].Elements["key-1"] = feature.Nil{}
|
||||||
m, err = r2.execute(f)
|
m, err = r2.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r2.Labels, m, "keys should have matched")
|
assert.Equal(t, r2.Labels, m, "keys should have matched")
|
||||||
|
|
||||||
|
@ -99,20 +96,18 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.vf-1",
|
Feature: "domain-1.vf-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"key-1": MustCreateMatchExpression(MatchIn, "val-1")},
|
||||||
"key-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-1"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
m, err = r3.execute(f)
|
m, err = r3.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "values should not have matched")
|
assert.Nil(t, m, "values should not have matched")
|
||||||
|
|
||||||
d.Values["vf-1"].Elements["key-1"] = "val-1"
|
d.Values["vf-1"].Elements["key-1"] = "val-1"
|
||||||
m, err = r3.execute(f)
|
m, err = r3.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r3.Labels, m, "values should have matched")
|
assert.Equal(t, r3.Labels, m, "values should have matched")
|
||||||
|
|
||||||
|
@ -122,20 +117,18 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.if-1",
|
Feature: "domain-1.if-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"attr-1": MustCreateMatchExpression(MatchIn, "val-1")},
|
||||||
"attr-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-1"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
m, err = r4.execute(f)
|
m, err = r4.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "instances should not have matched")
|
assert.Nil(t, m, "instances should not have matched")
|
||||||
|
|
||||||
d.Instances["if-1"].Elements[0].Attributes["attr-1"] = "val-1"
|
d.Instances["if-1"].Elements[0].Attributes["attr-1"] = "val-1"
|
||||||
m, err = r4.execute(f)
|
m, err = r4.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r4.Labels, m, "instances should have matched")
|
assert.Equal(t, r4.Labels, m, "instances should have matched")
|
||||||
|
|
||||||
|
@ -145,28 +138,24 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.vf-1",
|
Feature: "domain-1.vf-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"key-1": MustCreateMatchExpression(MatchIn, "val-x")},
|
||||||
"key-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-x"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.if-1",
|
Feature: "domain-1.if-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"attr-1": MustCreateMatchExpression(MatchIn, "val-1")},
|
||||||
"attr-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-1"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
m, err = r5.execute(f)
|
m, err = r5.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "instances should not have matched")
|
assert.Nil(t, m, "instances should not have matched")
|
||||||
|
|
||||||
r5.MatchFeatures[0].MatchExpressions.Expressions["key-1"] = nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-1")
|
r5.MatchFeatures[0].MatchExpressions.Expressions["key-1"] = MustCreateMatchExpression(MatchIn, "val-1")
|
||||||
m, err = r5.execute(f)
|
m, err = r5.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r5.Labels, m, "instances should have matched")
|
assert.Equal(t, r5.Labels, m, "instances should have matched")
|
||||||
|
|
||||||
|
@ -176,16 +165,14 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.kf-1",
|
Feature: "domain-1.kf-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"key-na": MustCreateMatchExpression(MatchExists)},
|
||||||
"key-na": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchExists),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
m, err = r5.execute(f)
|
m, err = r5.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Nil(t, m, "instances should not have matched")
|
assert.Nil(t, m, "instances should not have matched")
|
||||||
|
|
||||||
|
@ -194,16 +181,14 @@ func TestRule(t *testing.T) {
|
||||||
MatchFeatures: FeatureMatcher{
|
MatchFeatures: FeatureMatcher{
|
||||||
FeatureMatcherTerm{
|
FeatureMatcherTerm{
|
||||||
Feature: "domain-1.kf-1",
|
Feature: "domain-1.kf-1",
|
||||||
MatchExpressions: nfdv1alpha1.MatchExpressionSet{
|
MatchExpressions: MatchExpressionSet{
|
||||||
Expressions: nfdv1alpha1.Expressions{
|
Expressions: Expressions{"key-1": MustCreateMatchExpression(MatchExists)},
|
||||||
"key-1": nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchExists),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
r5.MatchFeatures[0].MatchExpressions.Expressions["key-1"] = nfdv1alpha1.MustCreateMatchExpression(nfdv1alpha1.MatchIn, "val-1")
|
r5.MatchFeatures[0].MatchExpressions.Expressions["key-1"] = MustCreateMatchExpression(MatchIn, "val-1")
|
||||||
m, err = r5.execute(f)
|
m, err = r5.Execute(f)
|
||||||
assert.Nilf(t, err, "unexpected error: %v", err)
|
assert.Nilf(t, err, "unexpected error: %v", err)
|
||||||
assert.Equal(t, r5.Labels, m, "instances should have matched")
|
assert.Equal(t, r5.Labels, m, "instances should have matched")
|
||||||
}
|
}
|
|
@ -51,21 +51,7 @@ type LegacyRule struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
Name string `json:"name"`
|
nfdv1alpha1.Rule
|
||||||
Labels map[string]string `json:"labels"`
|
|
||||||
MatchFeatures FeatureMatcher `json:"matchFeatures"`
|
|
||||||
MatchAny []MatchAnyElem `json:"matchAny"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MatchAnyElem struct {
|
|
||||||
MatchFeatures FeatureMatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
type FeatureMatcher []FeatureMatcherTerm
|
|
||||||
|
|
||||||
type FeatureMatcherTerm struct {
|
|
||||||
Feature string
|
|
||||||
MatchExpressions nfdv1alpha1.MatchExpressionSet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type config []CustomRule
|
type config []CustomRule
|
||||||
|
@ -155,7 +141,7 @@ func (r *CustomRule) execute(features map[string]*feature.DomainFeatures) (map[s
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Rule != nil {
|
if r.Rule != nil {
|
||||||
ruleOut, err := r.Rule.execute(features)
|
ruleOut, err := r.Rule.Execute(features)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to execute rule %s: %w", r.Rule.Name, err)
|
return nil, fmt.Errorf("failed to execute rule %s: %w", r.Rule.Name, err)
|
||||||
}
|
}
|
||||||
|
@ -189,80 +175,6 @@ func (r *LegacyRule) execute(features map[string]*feature.DomainFeatures) (map[s
|
||||||
return map[string]string{r.Name: value}, nil
|
return map[string]string{r.Name: value}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) execute(features map[string]*feature.DomainFeatures) (map[string]string, error) {
|
|
||||||
if len(r.MatchAny) > 0 {
|
|
||||||
// Logical OR over the matchAny matchers
|
|
||||||
matched := false
|
|
||||||
for _, matcher := range r.MatchAny {
|
|
||||||
if m, err := matcher.match(features); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if m {
|
|
||||||
matched = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !matched {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(r.MatchFeatures) > 0 {
|
|
||||||
if m, err := r.MatchFeatures.match(features); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !m {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := make(map[string]string, len(r.Labels))
|
|
||||||
for k, v := range r.Labels {
|
|
||||||
labels[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *MatchAnyElem) match(features map[string]*feature.DomainFeatures) (bool, error) {
|
|
||||||
return e.MatchFeatures.match(features)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *FeatureMatcher) match(features map[string]*feature.DomainFeatures) (bool, error) {
|
|
||||||
// Logical AND over the terms
|
|
||||||
for _, term := range *m {
|
|
||||||
split := strings.SplitN(term.Feature, ".", 2)
|
|
||||||
if len(split) != 2 {
|
|
||||||
return false, fmt.Errorf("invalid selector %q: must be <domain>.<feature>", term.Feature)
|
|
||||||
}
|
|
||||||
domain := split[0]
|
|
||||||
// Ignore case
|
|
||||||
featureName := strings.ToLower(split[1])
|
|
||||||
|
|
||||||
domainFeatures, ok := features[domain]
|
|
||||||
if !ok {
|
|
||||||
return false, fmt.Errorf("unknown feature source/domain %q", domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
var m bool
|
|
||||||
var err error
|
|
||||||
if f, ok := domainFeatures.Keys[featureName]; ok {
|
|
||||||
m, err = term.MatchExpressions.MatchKeys(f.Elements)
|
|
||||||
} else if f, ok := domainFeatures.Values[featureName]; ok {
|
|
||||||
m, err = term.MatchExpressions.MatchValues(f.Elements)
|
|
||||||
} else if f, ok := domainFeatures.Instances[featureName]; ok {
|
|
||||||
m, err = term.MatchExpressions.MatchInstances(f.Elements)
|
|
||||||
} else {
|
|
||||||
return false, fmt.Errorf("%q feature of source/domain %q not available", featureName, domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
} else if !m {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LegacyMatcher) match() (bool, error) {
|
func (m *LegacyMatcher) match() (bool, error) {
|
||||||
allRules := []legacyRule{
|
allRules := []legacyRule{
|
||||||
m.PciID,
|
m.PciID,
|
||||||
|
|
Loading…
Reference in a new issue