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

nfd-worker: add core.sources config option

Add a config file option for controlling the enabled feature sources,
aimed at replacing the --sources command line flag which is now marked
as deprecated. The command line flag takes precedence over the config
file option.
This commit is contained in:
Markus Lehtonen 2020-12-01 15:53:04 +02:00
parent ed177350fc
commit 7e88f00e05
10 changed files with 102 additions and 75 deletions

View file

@ -93,7 +93,8 @@ func argsParse(argv []string) (worker.Args, error) {
[Default: ] [Default: ]
--sources=<sources> Comma separated list of feature sources. Special --sources=<sources> Comma separated list of feature sources. Special
value 'all' enables all feature sources. value 'all' enables all feature sources.
[Default: all] (DEPRECATED: This parameter should be set via the
config file)
--no-publish Do not publish discovered features to the --no-publish Do not publish discovered features to the
cluster-local Kubernetes API server. cluster-local Kubernetes API server.
--label-whitelist=<pattern> Regular expression to filter label names to --label-whitelist=<pattern> Regular expression to filter label names to
@ -125,7 +126,6 @@ func argsParse(argv []string) (worker.Args, error) {
args.Options = arguments["--options"].(string) args.Options = arguments["--options"].(string)
args.Server = arguments["--server"].(string) args.Server = arguments["--server"].(string)
args.ServerNameOverride = arguments["--server-name-override"].(string) args.ServerNameOverride = arguments["--server-name-override"].(string)
args.Sources = strings.Split(arguments["--sources"].(string), ",")
args.Oneshot = arguments["--oneshot"].(bool) args.Oneshot = arguments["--oneshot"].(bool)
// Parse deprecated/override args // Parse deprecated/override args
@ -150,5 +150,10 @@ func argsParse(argv []string) (worker.Args, error) {
args.SleepInterval = &s args.SleepInterval = &s
} }
} }
if v := arguments["--sources"]; v != nil {
fmt.Println(v)
s := strings.Split(v.(string), ",")
args.Sources = &s
}
return args, nil return args, nil
} }

View file

@ -23,8 +23,6 @@ import (
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
var allSources = []string{"all"}
func TestArgsParse(t *testing.T) { func TestArgsParse(t *testing.T) {
Convey("When parsing command line arguments", t, func() { Convey("When parsing command line arguments", t, func() {
Convey("When --no-publish and --oneshot flags are passed", func() { Convey("When --no-publish and --oneshot flags are passed", func() {
@ -34,7 +32,7 @@ func TestArgsParse(t *testing.T) {
So(args.SleepInterval, ShouldEqual, nil) So(args.SleepInterval, ShouldEqual, nil)
So(*args.NoPublish, ShouldBeTrue) So(*args.NoPublish, ShouldBeTrue)
So(args.Oneshot, ShouldBeTrue) So(args.Oneshot, ShouldBeTrue)
So(args.Sources, ShouldResemble, allSources) So(args.Sources, ShouldBeNil)
So(args.LabelWhiteList, ShouldBeNil) So(args.LabelWhiteList, ShouldBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })
@ -47,7 +45,7 @@ func TestArgsParse(t *testing.T) {
So(*args.SleepInterval, ShouldEqual, 30*time.Second) So(*args.SleepInterval, ShouldEqual, 30*time.Second)
So(args.NoPublish, ShouldBeNil) So(args.NoPublish, ShouldBeNil)
So(args.Oneshot, ShouldBeFalse) So(args.Oneshot, ShouldBeFalse)
So(args.Sources, ShouldResemble, []string{"fake1", "fake2", "fake3"}) So(*args.Sources, ShouldResemble, []string{"fake1", "fake2", "fake3"})
So(args.LabelWhiteList, ShouldBeNil) So(args.LabelWhiteList, ShouldBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })
@ -58,7 +56,7 @@ func TestArgsParse(t *testing.T) {
Convey("args.labelWhiteList is set to appropriate value and args.sources is set to default value", func() { Convey("args.labelWhiteList is set to appropriate value and args.sources is set to default value", func() {
So(args.NoPublish, ShouldBeNil) So(args.NoPublish, ShouldBeNil)
So(args.Sources, ShouldResemble, allSources) So(args.Sources, ShouldBeNil)
So(args.LabelWhiteList.String(), ShouldResemble, ".*rdt.*") So(args.LabelWhiteList.String(), ShouldResemble, ".*rdt.*")
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })
@ -72,7 +70,7 @@ func TestArgsParse(t *testing.T) {
So(args.CaFile, ShouldEqual, "ca") So(args.CaFile, ShouldEqual, "ca")
So(args.CertFile, ShouldEqual, "crt") So(args.CertFile, ShouldEqual, "crt")
So(args.KeyFile, ShouldEqual, "key") So(args.KeyFile, ShouldEqual, "key")
So(args.Sources, ShouldResemble, []string{"fake1", "fake2", "fake3"}) So(*args.Sources, ShouldResemble, []string{"fake1", "fake2", "fake3"})
So(args.LabelWhiteList, ShouldBeNil) So(args.LabelWhiteList, ShouldBeNil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })

View file

@ -141,6 +141,9 @@ nfd-worker --server-name-override=localhost
The `--sources` flag specifies a comma-separated list of enabled feature The `--sources` flag specifies a comma-separated list of enabled feature
sources. A special value `all` enables all feature sources. sources. A special value `all` enables all feature sources.
Note: This flag takes precedence over the `core.sources` configuration
file option.
Default: all Default: all
Example: Example:
@ -149,6 +152,9 @@ Example:
nfd-worker --sources=kernel,system,local nfd-worker --sources=kernel,system,local
``` ```
**DEPRECATED**: you should use the `core.sources` option in the
configuration file, instead.
### --no-publish ### --no-publish
The `--no-publish` flag disables all communication with the nfd-master, making The `--no-publish` flag disables all communication with the nfd-master, making

View file

@ -146,6 +146,7 @@ data:
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# sources: [all]
#sources: #sources:
# cpu: # cpu:
# cpuid: # cpuid:

View file

@ -106,6 +106,7 @@ data:
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# sources: [all]
#sources: #sources:
# cpu: # cpu:
# cpuid: # cpuid:

View file

@ -116,6 +116,7 @@ data:
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# sources: [all]
#sources: #sources:
# cpu: # cpu:
# cpuid: # cpuid:

View file

@ -2,6 +2,7 @@
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# sources: [all]
#sources: #sources:
# cpu: # cpu:
# cpuid: # cpuid:

View file

@ -95,7 +95,7 @@ func makeFakeFeatures(names []string) (source.Features, Labels) {
} }
func (w *nfdWorker) getSource(name string) source.FeatureSource { func (w *nfdWorker) getSource(name string) source.FeatureSource {
for _, s := range w.sources { for _, s := range w.realSources {
if s.Name() == name { if s.Name() == name {
return s return s
} }
@ -105,7 +105,7 @@ func (w *nfdWorker) getSource(name string) source.FeatureSource {
func TestConfigParse(t *testing.T) { func TestConfigParse(t *testing.T) {
Convey("When parsing configuration", t, func() { Convey("When parsing configuration", t, func() {
w, err := NewNfdWorker(Args{Sources: []string{"cpu", "kernel", "pci"}}) w, err := NewNfdWorker(Args{Sources: &[]string{"cpu", "kernel", "pci"}})
So(err, ShouldBeNil) So(err, ShouldBeNil)
worker := w.(*nfdWorker) worker := w.(*nfdWorker)
Convey("and a non-accessible file and some overrides are specified", func() { Convey("and a non-accessible file and some overrides are specified", func() {
@ -171,14 +171,14 @@ func TestNewNfdWorker(t *testing.T) {
}) })
worker := w.(*nfdWorker) worker := w.(*nfdWorker)
worker.configure("", "") worker.configure("", "")
Convey("no sources should be enabled and the whitelist regexp should be empty", func() { Convey("all sources should be enabled and the whitelist regexp should be empty", func() {
So(len(worker.sources), ShouldEqual, 0) So(len(worker.enabledSources), ShouldEqual, len(worker.realSources))
So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp) So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp)
}) })
}) })
Convey("with non-empty Sources arg specified", func() { Convey("with non-empty Sources arg specified", func() {
args := Args{Sources: []string{"fake"}} args := Args{Sources: &[]string{"fake"}}
w, err := NewNfdWorker(args) w, err := NewNfdWorker(args)
Convey("no error should be returned", func() { Convey("no error should be returned", func() {
So(err, ShouldBeNil) So(err, ShouldBeNil)
@ -186,8 +186,8 @@ func TestNewNfdWorker(t *testing.T) {
worker := w.(*nfdWorker) worker := w.(*nfdWorker)
worker.configure("", "") worker.configure("", "")
Convey("proper sources should be enabled", func() { Convey("proper sources should be enabled", func() {
So(len(worker.sources), ShouldEqual, 1) So(len(worker.enabledSources), ShouldEqual, 1)
So(worker.sources[0], ShouldHaveSameTypeAs, &fake.Source{}) So(worker.enabledSources[0], ShouldHaveSameTypeAs, &fake.Source{})
So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp) So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp)
}) })
}) })
@ -202,7 +202,6 @@ func TestNewNfdWorker(t *testing.T) {
worker.configure("", "") worker.configure("", "")
expectRegexp := regex{*regexp.MustCompile(".*rdt.*")} expectRegexp := regex{*regexp.MustCompile(".*rdt.*")}
Convey("proper labelWhiteList regexp should be produced", func() { Convey("proper labelWhiteList regexp should be produced", func() {
So(len(worker.sources), ShouldEqual, 0)
So(worker.config.Core.LabelWhiteList, ShouldResemble, expectRegexp) So(worker.config.Core.LabelWhiteList, ShouldResemble, expectRegexp)
}) })
}) })

View file

@ -68,6 +68,7 @@ type NFDConfig struct {
type coreConfig struct { type coreConfig struct {
LabelWhiteList regex LabelWhiteList regex
NoPublish bool NoPublish bool
Sources []string
SleepInterval duration SleepInterval duration
} }
@ -86,11 +87,11 @@ type Args struct {
Oneshot bool Oneshot bool
Server string Server string
ServerNameOverride string ServerNameOverride string
Sources []string
// Deprecated options that should be set via the config file // Deprecated options that should be set via the config file
LabelWhiteList *regexp.Regexp LabelWhiteList *regexp.Regexp
NoPublish *bool NoPublish *bool
SleepInterval *time.Duration SleepInterval *time.Duration
Sources *[]string
} }
type NfdWorker interface { type NfdWorker interface {
@ -103,7 +104,9 @@ type nfdWorker struct {
client pb.LabelerClient client pb.LabelerClient
configFilePath string configFilePath string
config *NFDConfig config *NFDConfig
sources []source.FeatureSource realSources []source.FeatureSource
testSources []source.FeatureSource
enabledSources []source.FeatureSource
} }
type regex struct { type regex struct {
@ -117,9 +120,27 @@ type duration struct {
// Create new NfdWorker instance. // Create new NfdWorker instance.
func NewNfdWorker(args Args) (NfdWorker, error) { func NewNfdWorker(args Args) (NfdWorker, error) {
nfd := &nfdWorker{ nfd := &nfdWorker{
args: args, args: args,
config: &NFDConfig{}, config: &NFDConfig{},
sources: []source.FeatureSource{}, realSources: []source.FeatureSource{
&cpu.Source{},
&iommu.Source{},
&kernel.Source{},
&memory.Source{},
&network.Source{},
&pci.Source{},
&storage.Source{},
&system.Source{},
&usb.Source{},
&custom.Source{},
// local needs to be the last source so that it is able to override
// labels from other sources
&local.Source{},
},
testSources: []source.FeatureSource{
&fake.Source{},
&panicfake.Source{},
},
} }
if args.ConfigFile != "" { if args.ConfigFile != "" {
@ -139,53 +160,6 @@ func NewNfdWorker(args Args) (NfdWorker, error) {
} }
} }
// Figure out active sources
allSources := []source.FeatureSource{
&cpu.Source{},
&iommu.Source{},
&kernel.Source{},
&memory.Source{},
&network.Source{},
&pci.Source{},
&storage.Source{},
&system.Source{},
&usb.Source{},
&custom.Source{},
// local needs to be the last source so that it is able to override
// labels from other sources
&local.Source{},
}
// Determine enabled feature
if len(args.Sources) == 1 && args.Sources[0] == "all" {
nfd.sources = allSources
} else {
// Add fake source which is only meant for testing. It will be enabled
// only if listed explicitly.
allSources = append(allSources, &fake.Source{})
allSources = append(allSources, &panicfake.Source{})
sourceWhiteList := map[string]struct{}{}
for _, s := range args.Sources {
sourceWhiteList[strings.TrimSpace(s)] = struct{}{}
}
nfd.sources = []source.FeatureSource{}
for _, s := range allSources {
if _, enabled := sourceWhiteList[s.Name()]; enabled {
nfd.sources = append(nfd.sources, s)
delete(sourceWhiteList, s.Name())
}
}
if len(sourceWhiteList) > 0 {
names := make([]string, 0, len(sourceWhiteList))
for n := range sourceWhiteList {
names = append(names, n)
}
stderrLogger.Printf("WARNING: skipping unknown source(s) %q specified in --sources", strings.Join(names, ", "))
}
}
return nfd, nil return nfd, nil
} }
@ -228,6 +202,7 @@ func newDefaultConfig() *NFDConfig {
Core: coreConfig{ Core: coreConfig{
LabelWhiteList: regex{*regexp.MustCompile("")}, LabelWhiteList: regex{*regexp.MustCompile("")},
SleepInterval: duration{60 * time.Second}, SleepInterval: duration{60 * time.Second},
Sources: []string{"all"},
}, },
} }
} }
@ -258,7 +233,7 @@ func (w *nfdWorker) Run() error {
select { select {
case <-labelTrigger: case <-labelTrigger:
// Get the set of feature labels. // Get the set of feature labels.
labels := createFeatureLabels(w.sources, w.config.Core.LabelWhiteList) labels := createFeatureLabels(w.enabledSources, w.config.Core.LabelWhiteList)
// Update the node with the feature labels. // Update the node with the feature labels.
if w.client != nil { if w.client != nil {
@ -386,12 +361,47 @@ func (c *coreConfig) sanitize() {
} }
} }
func (w *nfdWorker) configureCore(c coreConfig) {
// Determine enabled feature sourcds
sourceList := map[string]struct{}{}
all := false
for _, s := range c.Sources {
if s == "all" {
all = true
continue
}
sourceList[strings.TrimSpace(s)] = struct{}{}
}
w.enabledSources = []source.FeatureSource{}
for _, s := range w.realSources {
if _, enabled := sourceList[s.Name()]; all || enabled {
w.enabledSources = append(w.enabledSources, s)
delete(sourceList, s.Name())
}
}
for _, s := range w.testSources {
if _, enabled := sourceList[s.Name()]; enabled {
w.enabledSources = append(w.enabledSources, s)
delete(sourceList, s.Name())
}
}
if len(sourceList) > 0 {
names := make([]string, 0, len(sourceList))
for n := range sourceList {
names = append(names, n)
}
stderrLogger.Printf("WARNING: skipping unknown source(s) %q specified in core.sources (or --sources)", strings.Join(names, ", "))
}
}
// Parse configuration options // Parse configuration options
func (w *nfdWorker) configure(filepath string, overrides string) { func (w *nfdWorker) configure(filepath string, overrides string) {
// Create a new default config // Create a new default config
c := newDefaultConfig() c := newDefaultConfig()
c.Sources = make(map[string]source.Config, len(w.sources)) allSources := append(w.realSources, w.testSources...)
for _, s := range w.sources { c.Sources = make(map[string]source.Config, len(allSources))
for _, s := range allSources {
c.Sources[s.Name()] = s.NewConfig() c.Sources[s.Name()] = s.NewConfig()
} }
@ -423,13 +433,18 @@ func (w *nfdWorker) configure(filepath string, overrides string) {
if w.args.SleepInterval != nil { if w.args.SleepInterval != nil {
c.Core.SleepInterval = duration{*w.args.SleepInterval} c.Core.SleepInterval = duration{*w.args.SleepInterval}
} }
if w.args.Sources != nil {
c.Core.Sources = *w.args.Sources
}
c.Core.sanitize() c.Core.sanitize()
w.config = c w.config = c
// (Re-)configure all sources w.configureCore(c.Core)
for _, s := range w.sources {
// (Re-)configure all "real" sources, test sources are not configurable
for _, s := range allSources {
s.SetConfig(c.Sources[s.Name()]) s.SetConfig(c.Sources[s.Name()])
} }
} }

View file

@ -90,7 +90,7 @@ func TestRun(t *testing.T) {
defer teardownTest(ctx) defer teardownTest(ctx)
Convey("When running nfd-worker against nfd-master", t, func() { Convey("When running nfd-worker against nfd-master", t, func() {
Convey("When publishing features from fake source", func() { Convey("When publishing features from fake source", func() {
worker, _ := w.NewNfdWorker(w.Args{Oneshot: true, Sources: []string{"fake"}, Server: "localhost:8192"}) worker, _ := w.NewNfdWorker(w.Args{Oneshot: true, Sources: &[]string{"fake"}, Server: "localhost:8192"})
err := worker.Run() err := worker.Run()
Convey("No error should be returned", func() { Convey("No error should be returned", func() {
So(err, ShouldBeNil) So(err, ShouldBeNil)
@ -115,7 +115,7 @@ func TestRunTls(t *testing.T) {
CertFile: data.FilePath("nfd-test-worker.crt"), CertFile: data.FilePath("nfd-test-worker.crt"),
KeyFile: data.FilePath("nfd-test-worker.key"), KeyFile: data.FilePath("nfd-test-worker.key"),
Oneshot: true, Oneshot: true,
Sources: []string{"fake"}, Sources: &[]string{"fake"},
Server: "localhost:8192", Server: "localhost:8192",
ServerNameOverride: "nfd-test-master"} ServerNameOverride: "nfd-test-master"}
worker, _ := w.NewNfdWorker(workerArgs) worker, _ := w.NewNfdWorker(workerArgs)