@@ -18,6 +18,7 @@ package nodevalidator
1818
1919import (
2020 "context"
21+ "fmt"
2122 "slices"
2223 "sort"
2324
@@ -62,12 +63,12 @@ func New(opts ...NodeValidatorOpts) nodeValidator {
6263func (nv * nodeValidator ) Execute (ctx context.Context ) ([]* CompatibilityStatus , error ) {
6364 spec , err := nv .artifactClient .FetchCompatibilitySpec (ctx )
6465 if err != nil {
65- return nil , err
66+ return nil , fmt . Errorf ( "failed to fetch compatibility spec: %w" , err )
6667 }
6768
6869 for _ , s := range nv .sources {
6970 if err := s .Discover (); err != nil {
70- return nil , err
71+ return nil , fmt . Errorf ( "error during discovery of source %s: %w" , s . Name (), err )
7172 }
7273 }
7374 features := source .GetAllFeatures ()
@@ -84,7 +85,7 @@ func (nv *nodeValidator) Execute(ctx context.Context) ([]*CompatibilityStatus, e
8485 if err != nil {
8586 return nil , err
8687 }
87- compat .Rules = append (compat .Rules , evaluateRuleStatus (& r , ruleOut .MatchStatus ))
88+ compat .Rules = append (compat .Rules , nv . evaluateRuleStatus (& r , ruleOut .MatchStatus ))
8889
8990 // Add the 'rule.matched' feature for backreference functionality
9091 features .InsertAttributeFeatures (nfdv1alpha1 .RuleBackrefDomain , nfdv1alpha1 .RuleBackrefFeature , ruleOut .Labels )
@@ -96,91 +97,100 @@ func (nv *nodeValidator) Execute(ctx context.Context) ([]*CompatibilityStatus, e
9697 return compats , nil
9798}
9899
99- func evaluateRuleStatus (rule * nfdv1alpha1.Rule , matchStatus * nodefeaturerule.MatchStatus ) ProcessedRuleStatus {
100- var matchedFeatureTerms nfdv1alpha1.FeatureMatcher
100+ func (nv * nodeValidator ) evaluateRuleStatus (rule * nfdv1alpha1.Rule , matchStatus * nodefeaturerule.MatchStatus ) ProcessedRuleStatus {
101101 out := ProcessedRuleStatus {Name : rule .Name , IsMatch : matchStatus .IsMatch }
102102
103- evaluateFeatureMatcher := func (featureMatcher , matchedFeatureTerms nfdv1alpha1.FeatureMatcher ) []MatchedExpression {
104- out := []MatchedExpression {}
105- for _ , term := range featureMatcher {
106- if term .MatchExpressions != nil {
107- for name , exp := range * term .MatchExpressions {
108- isMatch := false
109-
110- // Check if the expression matches
111- for _ , processedTerm := range matchedFeatureTerms {
112- if term .Feature != processedTerm .Feature || processedTerm .MatchExpressions == nil {
113- continue
114- }
115- pexp , ok := (* processedTerm .MatchExpressions )[name ]
116- if isMatch = ok && exp .Op == pexp .Op && slices .Equal (exp .Value , pexp .Value ); isMatch {
117- break
118- }
119- }
120-
121- out = append (out , MatchedExpression {
122- Feature : term .Feature ,
123- Name : name ,
124- Expression : exp ,
125- MatcherType : MatchExpressionType ,
126- IsMatch : isMatch ,
127- })
128- }
129- }
103+ matchedFeatureTerms := nfdv1alpha1.FeatureMatcher {}
104+ if m := matchStatus .MatchFeatureStatus ; m != nil {
105+ matchedFeatureTerms = m .MatchedFeaturesTerms
106+ }
107+ out .MatchedExpressions = nv .matchFeatureExpressions (rule .MatchFeatures , matchedFeatureTerms )
130108
131- if term .MatchName != nil {
132- isMatch := false
133- for _ , processedTerm := range matchStatus .MatchedFeaturesTerms {
134- if term .Feature != processedTerm .Feature || processedTerm .MatchName == nil {
135- continue
136- }
137- isMatch = term .MatchName .Op == processedTerm .MatchName .Op && slices .Equal (term .MatchName .Value , processedTerm .MatchName .Value )
138- if isMatch {
139- break
140- }
141- }
142- out = append (out , MatchedExpression {
143- Feature : term .Feature ,
144- Name : "" ,
145- Expression : term .MatchName ,
146- MatcherType : MatchNameType ,
147- IsMatch : isMatch ,
148- })
149- }
109+ for i , matchAnyElem := range rule .MatchAny {
110+ matchedFeatureTermsAny := nfdv1alpha1.FeatureMatcher {}
111+ if t := matchStatus .MatchAny [i ].MatchedFeaturesTerms ; t != nil {
112+ matchedFeatureTermsAny = t
150113 }
114+ matchedExpressions := nv .matchFeatureExpressions (matchAnyElem .MatchFeatures , matchedFeatureTermsAny )
115+ out .MatchedAny = append (out .MatchedAny , MatchAnyElem {MatchedExpressions : matchedExpressions })
116+ }
151117
152- // For reproducible output sort by name, feature, expression.
153- sort .Slice (out , func (i , j int ) bool {
154- if out [i ].Feature != out [j ].Feature {
155- return out [i ].Feature < out [j ].Feature
156- }
157- if out [i ].Name != out [j ].Name {
158- return out [i ].Name < out [j ].Name
159- }
160- return out [i ].Expression .String () < out [j ].Expression .String ()
161- })
118+ return out
119+ }
162120
163- return out
164- }
121+ func ( nv * nodeValidator ) matchFeatureExpressions ( featureMatcher , matchedFeatureTerms nfdv1alpha1. FeatureMatcher ) [] MatchedExpression {
122+ var out [] MatchedExpression
165123
166- if matchFeatures := rule .MatchFeatures ; matchFeatures != nil {
167- if matchStatus .MatchFeatureStatus != nil {
168- matchedFeatureTerms = matchStatus .MatchFeatureStatus .MatchedFeaturesTerms
124+ for _ , term := range featureMatcher {
125+ if term .MatchExpressions != nil {
126+ out = append (out , nv .matchExpressions (term , matchedFeatureTerms )... )
127+ }
128+ if term .MatchName != nil {
129+ out = append (out , nv .matchName (term , matchedFeatureTerms ))
169130 }
170- out .MatchedExpressions = evaluateFeatureMatcher (matchFeatures , matchedFeatureTerms )
171131 }
172132
173- for i , matchAnyElem := range rule .MatchAny {
174- if matchStatus .MatchAny [i ].MatchedFeaturesTerms != nil {
175- matchedFeatureTerms = matchStatus .MatchAny [i ].MatchedFeaturesTerms
133+ // For reproducible output sort by name, feature, expression.
134+ sort .Slice (out , func (i , j int ) bool {
135+ if out [i ].Feature != out [j ].Feature {
136+ return out [i ].Feature < out [j ].Feature
176137 }
177- matchedExpressions := evaluateFeatureMatcher (matchAnyElem .MatchFeatures , matchedFeatureTerms )
178- out .MatchedAny = append (out .MatchedAny , MatchAnyElem {MatchedExpressions : matchedExpressions })
138+ if out [i ].Name != out [j ].Name {
139+ return out [i ].Name < out [j ].Name
140+ }
141+ return out [i ].Expression .String () < out [j ].Expression .String ()
142+ })
143+
144+ return out
145+ }
146+
147+ func (nodeValidator ) matchExpressions (term nfdv1alpha1.FeatureMatcherTerm , matchedFeatureTerms nfdv1alpha1.FeatureMatcher ) []MatchedExpression {
148+ var out []MatchedExpression
149+
150+ for name , exp := range * term .MatchExpressions {
151+ isMatch := false
152+ for _ , processedTerm := range matchedFeatureTerms {
153+ if term .Feature != processedTerm .Feature || processedTerm .MatchExpressions == nil {
154+ continue
155+ }
156+ pexp , ok := (* processedTerm .MatchExpressions )[name ]
157+ if isMatch = ok && exp .Op == pexp .Op && slices .Equal (exp .Value , pexp .Value ); isMatch {
158+ break
159+ }
160+ }
161+
162+ out = append (out , MatchedExpression {
163+ Feature : term .Feature ,
164+ Name : name ,
165+ Expression : exp ,
166+ MatcherType : MatchExpressionType ,
167+ IsMatch : isMatch ,
168+ })
179169 }
180170
181171 return out
182172}
183173
174+ func (nodeValidator ) matchName (term nfdv1alpha1.FeatureMatcherTerm , matchedFeatureTerms nfdv1alpha1.FeatureMatcher ) MatchedExpression {
175+ isMatch := false
176+ for _ , processedTerm := range matchedFeatureTerms {
177+ if term .Feature != processedTerm .Feature || processedTerm .MatchName == nil {
178+ continue
179+ }
180+ isMatch = term .MatchName .Op == processedTerm .MatchName .Op && slices .Equal (term .MatchName .Value , processedTerm .MatchName .Value )
181+ if isMatch {
182+ break
183+ }
184+ }
185+ return MatchedExpression {
186+ Feature : term .Feature ,
187+ Name : "" ,
188+ Expression : term .MatchName ,
189+ MatcherType : MatchNameType ,
190+ IsMatch : isMatch ,
191+ }
192+ }
193+
184194// NodeValidatorOpts applies certain options to the node validator.
185195type NodeValidatorOpts interface {
186196 apply (* nodeValidator )
0 commit comments