Skip to content

Commit 96262a3

Browse files
committed
nodefeaturegroup: implement vars
Implement handling of Vars and VarsTemplate fields or NodeFeatureGroup.
1 parent 76569bd commit 96262a3

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

pkg/apis/nfd/nodefeaturerule/rule.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,50 +147,71 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features, failFast bool)
147147
return ret, nil
148148
}
149149

150+
// GroupRuleOutput contains the output of group rule execution.
151+
type GroupRuleOutput struct {
152+
Vars map[string]string
153+
MatchStatus *MatchStatus
154+
}
155+
150156
// ExecuteGroupRule executes the GroupRule against a set of input features, and return true if the
151157
// rule matches.
152-
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features, failFast bool) (MatchStatus, error) {
158+
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features, failFast bool) (GroupRuleOutput, error) {
153159
var (
154160
matchStatus MatchStatus
155161
isMatch bool
156162
)
163+
vars := make(map[string]string)
164+
157165
if n := len(r.MatchAny); n > 0 {
158166
matchStatus.MatchAny = make([]*MatchFeatureStatus, 0, n)
159167
// Logical OR over the matchAny matchers
160168
for _, matcher := range r.MatchAny {
161169
matched, featureStatus, err := evaluateMatchAnyElem(&matcher, features, failFast)
162170
if err != nil {
163-
return matchStatus, err
171+
return GroupRuleOutput{}, err
164172
} else if matched {
165173
isMatch = true
166174
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(featureStatus.MatchedFeatures))
167175

168-
if failFast {
176+
if r.VarsTemplate == "" && failFast {
169177
// there's no need to evaluate other matchers in MatchAny
178+
// if there are no templates to be executed on them
170179
break
171180
}
181+
182+
if err := executeTemplate(r.VarsTemplate, featureStatus.MatchedFeatures, vars); err != nil {
183+
return GroupRuleOutput{}, err
184+
}
172185
}
173186
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
174187
}
175188
if !isMatch && failFast {
176-
return matchStatus, nil
189+
return GroupRuleOutput{MatchStatus: &matchStatus}, nil
177190
}
178191
}
179192

180193
if len(r.MatchFeatures) > 0 {
181194
var err error
182195
if isMatch, matchStatus.MatchFeatureStatus, err = evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
183-
return matchStatus, err
196+
return GroupRuleOutput{}, err
184197
} else if !isMatch {
185198
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
186-
return matchStatus, nil
199+
return GroupRuleOutput{MatchStatus: &matchStatus}, nil
200+
}
201+
if err := executeTemplate(r.VarsTemplate, matchStatus.MatchedFeatures, vars); err != nil {
202+
return GroupRuleOutput{}, err
187203
}
188204
}
189205

206+
maps.Copy(vars, r.Vars)
190207
matchStatus.IsMatch = true
191208

192-
klog.V(2).InfoS("rule matched", "ruleName", r.Name)
193-
return matchStatus, nil
209+
ret := GroupRuleOutput{
210+
Vars: vars,
211+
MatchStatus: &matchStatus,
212+
}
213+
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
214+
return ret, nil
194215
}
195216

196217
func executeTemplate(tmpl string, in matchedFeatures, out map[string]string) error {

pkg/nfd-master/nfd-master.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
717717
if err != nil {
718718
return fmt.Errorf("failed to get nodes: %w", err)
719719
}
720-
nodeFeaturesList := make([]*nfdv1alpha1.NodeFeature, 0)
720+
nodeFeaturesList := make([]*nfdv1alpha1.Features, 0)
721721
for _, node := range nodes.Items {
722722
// Merge all NodeFeature objects into a single NodeFeatureSpec
723723
nodeFeatures, err := m.getAndMergeNodeFeatures(node.Name)
@@ -728,22 +728,22 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
728728
// Nothing to do for this node
729729
continue
730730
}
731-
nodeFeaturesList = append(nodeFeaturesList, nodeFeatures)
731+
nodeFeaturesList = append(nodeFeaturesList, &nodeFeatures.Spec.Features)
732732
}
733733

734734
// Execute rules and create matching groups
735735
nodePool := make([]nfdv1alpha1.FeatureGroupNode, 0)
736736
nodeGroupValidator := make(map[string]bool)
737-
for _, rule := range nodeFeatureGroup.Spec.Rules {
738-
for _, feature := range nodeFeaturesList {
739-
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features, true)
737+
for _, features := range nodeFeaturesList {
738+
for _, rule := range nodeFeatureGroup.Spec.Rules {
739+
ruleOut, err := nodefeaturerule.ExecuteGroupRule(&rule, features, true)
740740
if err != nil {
741741
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
742742
continue
743743
}
744744

745-
if match.IsMatch {
746-
system := feature.Spec.Features.Attributes["system.name"]
745+
if ruleOut.MatchStatus.IsMatch {
746+
system := features.Attributes["system.name"]
747747
nodeName := system.Elements["nodename"]
748748
if _, ok := nodeGroupValidator[nodeName]; !ok {
749749
nodePool = append(nodePool, nfdv1alpha1.FeatureGroupNode{
@@ -752,6 +752,9 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
752752
nodeGroupValidator[nodeName] = true
753753
}
754754
}
755+
756+
// Feed back vars from rule output to features map for subsequent rules to match
757+
features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Vars)
755758
}
756759
}
757760

0 commit comments

Comments
 (0)