1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2025-03-17 05:48:21 +00:00

nodefeaturegroup: implement vars

Implement handling of Vars and VarsTemplate fields or NodeFeatureGroup.
This commit is contained in:
Markus Lehtonen 2025-03-03 15:02:31 +02:00
parent 76569bd846
commit 96262a3784
2 changed files with 39 additions and 15 deletions

View file

@ -147,50 +147,71 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features, failFast bool)
return ret, nil
}
// GroupRuleOutput contains the output of group rule execution.
type GroupRuleOutput struct {
Vars map[string]string
MatchStatus *MatchStatus
}
// ExecuteGroupRule executes the GroupRule against a set of input features, and return true if the
// rule matches.
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features, failFast bool) (MatchStatus, error) {
func ExecuteGroupRule(r *nfdv1alpha1.GroupRule, features *nfdv1alpha1.Features, failFast bool) (GroupRuleOutput, error) {
var (
matchStatus MatchStatus
isMatch bool
)
vars := make(map[string]string)
if n := len(r.MatchAny); n > 0 {
matchStatus.MatchAny = make([]*MatchFeatureStatus, 0, n)
// Logical OR over the matchAny matchers
for _, matcher := range r.MatchAny {
matched, featureStatus, err := evaluateMatchAnyElem(&matcher, features, failFast)
if err != nil {
return matchStatus, err
return GroupRuleOutput{}, err
} else if matched {
isMatch = true
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(featureStatus.MatchedFeatures))
if failFast {
if r.VarsTemplate == "" && failFast {
// there's no need to evaluate other matchers in MatchAny
// if there are no templates to be executed on them
break
}
if err := executeTemplate(r.VarsTemplate, featureStatus.MatchedFeatures, vars); err != nil {
return GroupRuleOutput{}, err
}
}
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
}
if !isMatch && failFast {
return matchStatus, nil
return GroupRuleOutput{MatchStatus: &matchStatus}, nil
}
}
if len(r.MatchFeatures) > 0 {
var err error
if isMatch, matchStatus.MatchFeatureStatus, err = evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
return matchStatus, err
return GroupRuleOutput{}, err
} else if !isMatch {
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
return matchStatus, nil
return GroupRuleOutput{MatchStatus: &matchStatus}, nil
}
if err := executeTemplate(r.VarsTemplate, matchStatus.MatchedFeatures, vars); err != nil {
return GroupRuleOutput{}, err
}
}
maps.Copy(vars, r.Vars)
matchStatus.IsMatch = true
klog.V(2).InfoS("rule matched", "ruleName", r.Name)
return matchStatus, nil
ret := GroupRuleOutput{
Vars: vars,
MatchStatus: &matchStatus,
}
klog.V(2).InfoS("rule matched", "ruleName", r.Name, "ruleOutput", utils.DelayedDumper(ret))
return ret, nil
}
func executeTemplate(tmpl string, in matchedFeatures, out map[string]string) error {

View file

@ -717,7 +717,7 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
if err != nil {
return fmt.Errorf("failed to get nodes: %w", err)
}
nodeFeaturesList := make([]*nfdv1alpha1.NodeFeature, 0)
nodeFeaturesList := make([]*nfdv1alpha1.Features, 0)
for _, node := range nodes.Items {
// Merge all NodeFeature objects into a single NodeFeatureSpec
nodeFeatures, err := m.getAndMergeNodeFeatures(node.Name)
@ -728,22 +728,22 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
// Nothing to do for this node
continue
}
nodeFeaturesList = append(nodeFeaturesList, nodeFeatures)
nodeFeaturesList = append(nodeFeaturesList, &nodeFeatures.Spec.Features)
}
// Execute rules and create matching groups
nodePool := make([]nfdv1alpha1.FeatureGroupNode, 0)
nodeGroupValidator := make(map[string]bool)
for _, rule := range nodeFeatureGroup.Spec.Rules {
for _, feature := range nodeFeaturesList {
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features, true)
for _, features := range nodeFeaturesList {
for _, rule := range nodeFeatureGroup.Spec.Rules {
ruleOut, err := nodefeaturerule.ExecuteGroupRule(&rule, features, true)
if err != nil {
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
continue
}
if match.IsMatch {
system := feature.Spec.Features.Attributes["system.name"]
if ruleOut.MatchStatus.IsMatch {
system := features.Attributes["system.name"]
nodeName := system.Elements["nodename"]
if _, ok := nodeGroupValidator[nodeName]; !ok {
nodePool = append(nodePool, nfdv1alpha1.FeatureGroupNode{
@ -752,6 +752,9 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
nodeGroupValidator[nodeName] = true
}
}
// Feed back vars from rule output to features map for subsequent rules to match
features.InsertAttributeFeatures(nfdv1alpha1.RuleBackrefDomain, nfdv1alpha1.RuleBackrefFeature, ruleOut.Vars)
}
}