Skip to content

Commit a809292

Browse files
committed
source/custom: use internal api for config parsing
Change the custom feature source of nfd-worker to use the newly added internal config API for its own configuration. It now uses the internal types for json/yaml unmarshalling but converts them to external nfdv1alpha1 API to do the actual rule matching as the internal API does not duplicate that functionality.
1 parent 185b406 commit a809292

File tree

3 files changed

+61
-45
lines changed

3 files changed

+61
-45
lines changed

source/custom/custom.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,21 @@ package custom
1818

1919
import (
2020
"fmt"
21+
"os"
2122

2223
"k8s.io/klog/v2"
2324

2425
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
2526
"sigs.k8s.io/node-feature-discovery/pkg/utils"
2627
"sigs.k8s.io/node-feature-discovery/source"
28+
api "sigs.k8s.io/node-feature-discovery/source/custom/api"
2729
)
2830

2931
// Name of this feature source
3032
const Name = "custom"
3133

32-
type CustomRule struct {
33-
nfdv1alpha1.Rule
34-
}
35-
36-
type config []CustomRule
34+
// The config files use the internal API type.
35+
type config []api.Rule
3736

3837
// newDefaultConfig returns a new config with pre-populated defaults
3938
func newDefaultConfig() *config {
@@ -43,13 +42,19 @@ func newDefaultConfig() *config {
4342
// customSource implements the LabelSource and ConfigurableSource interfaces.
4443
type customSource struct {
4544
config *config
45+
// The rules are stored in the NFD API format that is a superset of our
46+
// internal API and provides the functions for rule matching.
47+
rules []nfdv1alpha1.Rule
4648
}
4749

4850
// Singleton source instance
4951
var (
50-
src = customSource{config: newDefaultConfig()}
51-
_ source.LabelSource = &src
52-
_ source.ConfigurableSource = &src
52+
src = customSource{
53+
config: &config{},
54+
rules: []nfdv1alpha1.Rule{},
55+
}
56+
_ source.LabelSource = &src
57+
_ source.ConfigurableSource = &src
5358
)
5459

5560
// Name returns the name of the feature source
@@ -65,6 +70,8 @@ func (s *customSource) GetConfig() source.Config { return s.config }
6570
func (s *customSource) SetConfig(conf source.Config) {
6671
switch v := conf.(type) {
6772
case *config:
73+
r := []api.Rule(*v)
74+
s.rules = convertInternalRulesToNfdApi(&r)
6875
s.config = v
6976
default:
7077
panic(fmt.Sprintf("invalid config type: %T", conf))
@@ -80,8 +87,8 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) {
8087
features := source.GetAllFeatures()
8188

8289
labels := source.FeatureLabels{}
83-
allFeatureConfig := append(getStaticFeatureConfig(), *s.config...)
84-
allFeatureConfig = append(allFeatureConfig, getDirectoryFeatureConfig()...)
90+
allFeatureConfig := append(getStaticRules(), s.rules...)
91+
allFeatureConfig = append(allFeatureConfig, getDropinDirRules()...)
8592
klog.V(2).InfoS("resolving custom features", "configuration", utils.DelayedDumper(allFeatureConfig))
8693
// Iterate over features
8794
for _, rule := range allFeatureConfig {
@@ -102,6 +109,17 @@ func (s *customSource) GetLabels() (source.FeatureLabels, error) {
102109
return labels, nil
103110
}
104111

112+
func convertInternalRulesToNfdApi(in *[]api.Rule) []nfdv1alpha1.Rule {
113+
out := make([]nfdv1alpha1.Rule, len(*in))
114+
for i := range *in {
115+
if err := api.ConvertRuleToV1alpha1(&(*in)[i], &out[i]); err != nil {
116+
klog.ErrorS(err, "FATAL: API conversion failed")
117+
os.Exit(255)
118+
}
119+
}
120+
return out
121+
}
122+
105123
func init() {
106124
source.Register(&src)
107125
}

source/custom/directory_features.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,24 @@ import (
2222
"strings"
2323

2424
"k8s.io/klog/v2"
25+
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
26+
api "sigs.k8s.io/node-feature-discovery/source/custom/api"
2527
"sigs.k8s.io/yaml"
2628
)
2729

2830
// Directory stores the full path for the custom sources folder
2931
const Directory = "/etc/kubernetes/node-feature-discovery/custom.d"
3032

31-
// getDirectoryFeatureConfig returns features configured in the "/etc/kubernetes/node-feature-discovery/custom.d"
33+
// getDropinDirRules returns features configured in the "/etc/kubernetes/node-feature-discovery/custom.d"
3234
// host directory and its 1st level subdirectories, which can be populated e.g. by ConfigMaps
33-
func getDirectoryFeatureConfig() []CustomRule {
35+
func getDropinDirRules() []nfdv1alpha1.Rule {
3436
features := readDir(Directory, true)
3537
klog.V(3).InfoS("all custom feature specs from config dir", "featureSpecs", features)
3638
return features
3739
}
3840

39-
func readDir(dirName string, recursive bool) []CustomRule {
40-
features := make([]CustomRule, 0)
41+
func readDir(dirName string, recursive bool) []nfdv1alpha1.Rule {
42+
features := make([]nfdv1alpha1.Rule, 0)
4143

4244
klog.V(4).InfoS("reading directory", "path", dirName)
4345
files, err := os.ReadDir(dirName)
@@ -74,14 +76,14 @@ func readDir(dirName string, recursive bool) []CustomRule {
7476
continue
7577
}
7678

77-
config := &[]CustomRule{}
79+
config := &[]api.Rule{}
7880
err = yaml.UnmarshalStrict(bytes, config)
7981
if err != nil {
8082
klog.ErrorS(err, "could not parse file", "path", fileName)
8183
continue
8284
}
8385

84-
features = append(features, *config...)
86+
features = append(features, convertInternalRulesToNfdApi(config)...)
8587
}
8688
return features
8789
}

source/custom/static_features.go

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,40 +20,36 @@ import (
2020
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
2121
)
2222

23-
// getStaticFeatures returns statically configured custom features to discover
23+
// getStaticRules returns statically configured custom features to discover
2424
// e.g RMDA related features. NFD configuration file may extend these custom features by adding rules.
25-
func getStaticFeatureConfig() []CustomRule {
26-
return []CustomRule{
27-
{
28-
nfdv1alpha1.Rule{
29-
Name: "RDMA capable static rule",
30-
Labels: map[string]string{"rdma.capable": "true"},
31-
MatchFeatures: nfdv1alpha1.FeatureMatcher{
32-
nfdv1alpha1.FeatureMatcherTerm{
33-
Feature: "pci.device",
34-
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{
35-
"vendor": &nfdv1alpha1.MatchExpression{
36-
Op: nfdv1alpha1.MatchIn,
37-
Value: nfdv1alpha1.MatchValue{"15b3"}},
38-
},
25+
func getStaticRules() []nfdv1alpha1.Rule {
26+
return []nfdv1alpha1.Rule{
27+
nfdv1alpha1.Rule{
28+
Name: "RDMA capable static rule",
29+
Labels: map[string]string{"rdma.capable": "true"},
30+
MatchFeatures: nfdv1alpha1.FeatureMatcher{
31+
nfdv1alpha1.FeatureMatcherTerm{
32+
Feature: "pci.device",
33+
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{
34+
"vendor": &nfdv1alpha1.MatchExpression{
35+
Op: nfdv1alpha1.MatchIn,
36+
Value: nfdv1alpha1.MatchValue{"15b3"}},
3937
},
4038
},
4139
},
4240
},
43-
{
44-
nfdv1alpha1.Rule{
45-
Name: "RDMA available static rule",
46-
Labels: map[string]string{"rdma.available": "true"},
47-
MatchFeatures: nfdv1alpha1.FeatureMatcher{
48-
nfdv1alpha1.FeatureMatcherTerm{
49-
Feature: "kernel.loadedmodule",
50-
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{
51-
"ib_uverbs": &nfdv1alpha1.MatchExpression{
52-
Op: nfdv1alpha1.MatchExists,
53-
},
54-
"rdma_ucm": &nfdv1alpha1.MatchExpression{
55-
Op: nfdv1alpha1.MatchExists,
56-
},
41+
nfdv1alpha1.Rule{
42+
Name: "RDMA available static rule",
43+
Labels: map[string]string{"rdma.available": "true"},
44+
MatchFeatures: nfdv1alpha1.FeatureMatcher{
45+
nfdv1alpha1.FeatureMatcherTerm{
46+
Feature: "kernel.loadedmodule",
47+
MatchExpressions: &nfdv1alpha1.MatchExpressionSet{
48+
"ib_uverbs": &nfdv1alpha1.MatchExpression{
49+
Op: nfdv1alpha1.MatchExists,
50+
},
51+
"rdma_ucm": &nfdv1alpha1.MatchExpression{
52+
Op: nfdv1alpha1.MatchExists,
5753
},
5854
},
5955
},

0 commit comments

Comments
 (0)