mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-17 13:58:21 +00:00
nodefeaturegroup: implement vars
Implement handling of Vars and VarsTemplate fields or NodeFeatureGroup.
This commit is contained in:
parent
76569bd846
commit
96262a3784
2 changed files with 39 additions and 15 deletions
|
@ -147,50 +147,71 @@ func Execute(r *nfdv1alpha1.Rule, features *nfdv1alpha1.Features, failFast bool)
|
||||||
return ret, nil
|
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
|
// ExecuteGroupRule executes the GroupRule against a set of input features, and return true if the
|
||||||
// rule matches.
|
// 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 (
|
var (
|
||||||
matchStatus MatchStatus
|
matchStatus MatchStatus
|
||||||
isMatch bool
|
isMatch bool
|
||||||
)
|
)
|
||||||
|
vars := make(map[string]string)
|
||||||
|
|
||||||
if n := len(r.MatchAny); n > 0 {
|
if n := len(r.MatchAny); n > 0 {
|
||||||
matchStatus.MatchAny = make([]*MatchFeatureStatus, 0, n)
|
matchStatus.MatchAny = make([]*MatchFeatureStatus, 0, n)
|
||||||
// Logical OR over the matchAny matchers
|
// Logical OR over the matchAny matchers
|
||||||
for _, matcher := range r.MatchAny {
|
for _, matcher := range r.MatchAny {
|
||||||
matched, featureStatus, err := evaluateMatchAnyElem(&matcher, features, failFast)
|
matched, featureStatus, err := evaluateMatchAnyElem(&matcher, features, failFast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return matchStatus, err
|
return GroupRuleOutput{}, err
|
||||||
} else if matched {
|
} else if matched {
|
||||||
isMatch = true
|
isMatch = true
|
||||||
klog.V(4).InfoS("matchAny matched", "ruleName", r.Name, "matchedFeatures", utils.DelayedDumper(featureStatus.MatchedFeatures))
|
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
|
// there's no need to evaluate other matchers in MatchAny
|
||||||
|
// if there are no templates to be executed on them
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := executeTemplate(r.VarsTemplate, featureStatus.MatchedFeatures, vars); err != nil {
|
||||||
|
return GroupRuleOutput{}, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
|
matchStatus.MatchAny = append(matchStatus.MatchAny, featureStatus)
|
||||||
}
|
}
|
||||||
if !isMatch && failFast {
|
if !isMatch && failFast {
|
||||||
return matchStatus, nil
|
return GroupRuleOutput{MatchStatus: &matchStatus}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.MatchFeatures) > 0 {
|
if len(r.MatchFeatures) > 0 {
|
||||||
var err error
|
var err error
|
||||||
if isMatch, matchStatus.MatchFeatureStatus, err = evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
|
if isMatch, matchStatus.MatchFeatureStatus, err = evaluateFeatureMatcher(&r.MatchFeatures, features, failFast); err != nil {
|
||||||
return matchStatus, err
|
return GroupRuleOutput{}, err
|
||||||
} else if !isMatch {
|
} else if !isMatch {
|
||||||
klog.V(2).InfoS("rule did not match", "ruleName", r.Name)
|
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
|
matchStatus.IsMatch = true
|
||||||
|
|
||||||
klog.V(2).InfoS("rule matched", "ruleName", r.Name)
|
ret := GroupRuleOutput{
|
||||||
return matchStatus, nil
|
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 {
|
func executeTemplate(tmpl string, in matchedFeatures, out map[string]string) error {
|
||||||
|
|
|
@ -717,7 +717,7 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get nodes: %w", err)
|
return fmt.Errorf("failed to get nodes: %w", err)
|
||||||
}
|
}
|
||||||
nodeFeaturesList := make([]*nfdv1alpha1.NodeFeature, 0)
|
nodeFeaturesList := make([]*nfdv1alpha1.Features, 0)
|
||||||
for _, node := range nodes.Items {
|
for _, node := range nodes.Items {
|
||||||
// Merge all NodeFeature objects into a single NodeFeatureSpec
|
// Merge all NodeFeature objects into a single NodeFeatureSpec
|
||||||
nodeFeatures, err := m.getAndMergeNodeFeatures(node.Name)
|
nodeFeatures, err := m.getAndMergeNodeFeatures(node.Name)
|
||||||
|
@ -728,22 +728,22 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
|
||||||
// Nothing to do for this node
|
// Nothing to do for this node
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodeFeaturesList = append(nodeFeaturesList, nodeFeatures)
|
nodeFeaturesList = append(nodeFeaturesList, &nodeFeatures.Spec.Features)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute rules and create matching groups
|
// Execute rules and create matching groups
|
||||||
nodePool := make([]nfdv1alpha1.FeatureGroupNode, 0)
|
nodePool := make([]nfdv1alpha1.FeatureGroupNode, 0)
|
||||||
nodeGroupValidator := make(map[string]bool)
|
nodeGroupValidator := make(map[string]bool)
|
||||||
for _, rule := range nodeFeatureGroup.Spec.Rules {
|
for _, features := range nodeFeaturesList {
|
||||||
for _, feature := range nodeFeaturesList {
|
for _, rule := range nodeFeatureGroup.Spec.Rules {
|
||||||
match, err := nodefeaturerule.ExecuteGroupRule(&rule, &feature.Spec.Features, true)
|
ruleOut, err := nodefeaturerule.ExecuteGroupRule(&rule, features, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
|
klog.ErrorS(err, "failed to evaluate rule", "ruleName", rule.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if match.IsMatch {
|
if ruleOut.MatchStatus.IsMatch {
|
||||||
system := feature.Spec.Features.Attributes["system.name"]
|
system := features.Attributes["system.name"]
|
||||||
nodeName := system.Elements["nodename"]
|
nodeName := system.Elements["nodename"]
|
||||||
if _, ok := nodeGroupValidator[nodeName]; !ok {
|
if _, ok := nodeGroupValidator[nodeName]; !ok {
|
||||||
nodePool = append(nodePool, nfdv1alpha1.FeatureGroupNode{
|
nodePool = append(nodePool, nfdv1alpha1.FeatureGroupNode{
|
||||||
|
@ -752,6 +752,9 @@ func (m *nfdMaster) nfdAPIUpdateNodeFeatureGroup(nfdClient nfdclientset.Interfac
|
||||||
nodeGroupValidator[nodeName] = true
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue