1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2025-03-14 20:56:42 +00:00

Merge pull request #605 from marquiz/devel/feature-source-config-flag

nfd-worker: add core.featureSources config option
This commit is contained in:
Kubernetes Prow Robot 2021-12-03 06:22:28 -08:00 committed by GitHub
commit 6071b04370
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 160 additions and 29 deletions

View file

@ -80,6 +80,8 @@ func parseArgs(flags *flag.FlagSet, osArgs ...string) *worker.Args {
switch f.Name { switch f.Name {
case "no-publish": case "no-publish":
args.Overrides.NoPublish = overrides.NoPublish args.Overrides.NoPublish = overrides.NoPublish
case "feature-sources":
args.Overrides.FeatureSources = overrides.FeatureSources
case "label-sources": case "label-sources":
args.Overrides.LabelSources = overrides.LabelSources args.Overrides.LabelSources = overrides.LabelSources
case "label-whitelist": case "label-whitelist":
@ -123,12 +125,16 @@ func initFlags(flagset *flag.FlagSet) (*worker.Args, *worker.ConfigOverrideArgs)
// Flags overlapping with config file options // Flags overlapping with config file options
overrides := &worker.ConfigOverrideArgs{ overrides := &worker.ConfigOverrideArgs{
LabelWhiteList: &utils.RegexpVal{}, LabelWhiteList: &utils.RegexpVal{},
FeatureSources: &utils.StringSliceVal{},
LabelSources: &utils.StringSliceVal{}, LabelSources: &utils.StringSliceVal{},
} }
overrides.NoPublish = flagset.Bool("no-publish", false, overrides.NoPublish = flagset.Bool("no-publish", false,
"Do not publish discovered features, disable connection to nfd-master.") "Do not publish discovered features, disable connection to nfd-master.")
flagset.Var(overrides.FeatureSources, "feature-sources",
"Comma separated list of feature sources. Special value 'all' enables all sources. "+
"Prefix the source name with '-' to disable it.")
flagset.Var(overrides.LabelSources, "label-sources", flagset.Var(overrides.LabelSources, "label-sources",
"Comma separated list of label sources. Special value 'all' enables all feature sources. "+ "Comma separated list of label sources. Special value 'all' enables all sources. "+
"Prefix the source name with '-' to disable it.") "Prefix the source name with '-' to disable it.")
flagset.Var(overrides.LabelWhiteList, "label-whitelist", flagset.Var(overrides.LabelWhiteList, "label-whitelist",
"Regular expression to filter label names to publish to the Kubernetes API server. "+ "Regular expression to filter label names to publish to the Kubernetes API server. "+

View file

@ -38,6 +38,7 @@ func TestParseArgs(t *testing.T) {
So(args.Overrides.NoPublish, ShouldBeNil) So(args.Overrides.NoPublish, ShouldBeNil)
So(args.Overrides.LabelWhiteList, ShouldBeNil) So(args.Overrides.LabelWhiteList, ShouldBeNil)
So(args.Overrides.SleepInterval, ShouldBeNil) So(args.Overrides.SleepInterval, ShouldBeNil)
So(args.Overrides.FeatureSources, ShouldBeNil)
So(args.Overrides.LabelSources, ShouldBeNil) So(args.Overrides.LabelSources, ShouldBeNil)
}) })
}) })
@ -46,6 +47,7 @@ func TestParseArgs(t *testing.T) {
args := parseArgs(flags, args := parseArgs(flags,
"-no-publish", "-no-publish",
"-label-whitelist=.*rdt.*", "-label-whitelist=.*rdt.*",
"-feature-sources=cpu",
"-label-sources=fake1,fake2,fake3", "-label-sources=fake1,fake2,fake3",
"-sleep-interval=30s") "-sleep-interval=30s")
@ -53,6 +55,7 @@ func TestParseArgs(t *testing.T) {
So(args.Oneshot, ShouldBeFalse) So(args.Oneshot, ShouldBeFalse)
So(*args.Overrides.NoPublish, ShouldBeTrue) So(*args.Overrides.NoPublish, ShouldBeTrue)
So(*args.Overrides.SleepInterval, ShouldEqual, 30*time.Second) So(*args.Overrides.SleepInterval, ShouldEqual, 30*time.Second)
So(*args.Overrides.FeatureSources, ShouldResemble, utils.StringSliceVal{"cpu"})
So(*args.Overrides.LabelSources, ShouldResemble, utils.StringSliceVal{"fake1", "fake2", "fake3"}) So(*args.Overrides.LabelSources, ShouldResemble, utils.StringSliceVal{"fake1", "fake2", "fake3"})
So(args.Overrides.LabelWhiteList.Regexp.String(), ShouldResemble, ".*rdt.*") So(args.Overrides.LabelWhiteList.Regexp.String(), ShouldResemble, ".*rdt.*")
}) })

View file

@ -2,6 +2,7 @@
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# featureSources: [all]
# labelSources: [all] # labelSources: [all]
# klog: # klog:
# addDirHeader: false # addDirHeader: false

View file

@ -91,6 +91,7 @@ worker:
# labelWhiteList: # labelWhiteList:
# noPublish: false # noPublish: false
# sleepInterval: 60s # sleepInterval: 60s
# featureSources: [all]
# labelSources: [all] # labelSources: [all]
# klog: # klog:
# addDirHeader: false # addDirHeader: false

View file

@ -136,6 +136,28 @@ Example:
nfd-worker -server-name-override=localhost nfd-worker -server-name-override=localhost
``` ```
### -feature-sources
The `-feature-sources` flag specifies a comma-separated list of enabled feature
sources. A special value `all` enables all sources. Prefixing a source name
with `-` indicates that the source will be disabled instead - this is only
meaningful when used in conjunction with `all`. This command line flag allows
completely disabling the feature detection so that neither standard feature
labels are generated nor the raw feature data is available for custom rule
processing. Consider using the `core.featureSources` config file option,
instead, allowing dynamic configurability.
Note: This flag takes precedence over the `core.featureSources` configuration
file option.
Default: all
Example:
```bash
nfd-worker -feature-sources=all,-pci
```
### -label-sources ### -label-sources
The `-label-sources` flag specifies a comma-separated list of enabled label The `-label-sources` flag specifies a comma-separated list of enabled label

View file

@ -43,12 +43,44 @@ core:
sleepInterval: 60s sleepInterval: 60s
``` ```
### core.featureSources
`core.featureSources` specifies the list of enabled feature sources. A special
value `all` enables all sources. Prefixing a source name with `-` indicates
that the source will be disabled instead - this is only meaningful when used in
conjunction with `all`. This option allows completely disabling the feature
detection so that neither standard feature labels are generated nor the raw
feature data is available for custom rule processing.
Default: `[all]`
Example:
```yaml
core:
# Enable all but cpu and local sources
featureSources:
- "all"
- "-cpu"
- "-local"
```
```yaml
core:
# Enable only cpu and local sources
featureSources:
- "cpu"
- "local"
```
### core.labelSources ### core.labelSources
`core.labelSources` specifies the list of enabled label sources. A special `core.labelSources` specifies the list of enabled label sources. A special
value `all` enables all sources. Prefixing a source name with `-` indicates value `all` enables all sources. Prefixing a source name with `-` indicates
that the source will be disabled instead - this is only meaningful when used in that the source will be disabled instead - this is only meaningful when used in
conjunction with `all`. conjunction with `all`. This configuration option affects the generation of
node labels but not the actual discovery of the underlying feature data that is
used e.g. in custom/`NodeFeatureRule` rules.
Note: Overridden by the `-label-sources` and `-sources` command line flags and Note: Overridden by the `-label-sources` and `-sources` command line flags and
the `core.sources` configurations option (if any of them is specified). the `core.sources` configurations option (if any of them is specified).

View file

@ -107,15 +107,19 @@ func TestConfigParse(t *testing.T) {
Convey("core overrides should be in effect", func() { Convey("core overrides should be in effect", func() {
So(worker.config.Core.LabelSources, ShouldResemble, []string{"fake"}) So(worker.config.Core.LabelSources, ShouldResemble, []string{"fake"})
So(worker.config.Core.FeatureSources, ShouldResemble, []string{"all"})
So(worker.config.Core.NoPublish, ShouldBeTrue) So(worker.config.Core.NoPublish, ShouldBeTrue)
}) })
}) })
Convey("and a non-accessible file, but core cmdline flags and some overrides are specified", func() { Convey("and a non-accessible file, but core cmdline flags and some overrides are specified", func() {
worker.args = Args{Overrides: ConfigOverrideArgs{LabelSources: &utils.StringSliceVal{"cpu", "kernel", "pci"}}} worker.args = Args{Overrides: ConfigOverrideArgs{
LabelSources: &utils.StringSliceVal{"cpu", "kernel", "pci"},
FeatureSources: &utils.StringSliceVal{"cpu"}}}
So(worker.configure("non-existing-file", overrides), ShouldBeNil) So(worker.configure("non-existing-file", overrides), ShouldBeNil)
Convey("core cmdline flags should be in effect instead overrides", func() { Convey("core cmdline flags should be in effect instead overrides", func() {
So(worker.config.Core.LabelSources, ShouldResemble, []string{"cpu", "kernel", "pci"}) So(worker.config.Core.LabelSources, ShouldResemble, []string{"cpu", "kernel", "pci"})
So(worker.config.Core.FeatureSources, ShouldResemble, []string{"cpu"})
}) })
Convey("overrides should take effect", func() { Convey("overrides should take effect", func() {
So(worker.config.Core.NoPublish, ShouldBeTrue) So(worker.config.Core.NoPublish, ShouldBeTrue)
@ -131,6 +135,7 @@ func TestConfigParse(t *testing.T) {
_, err = f.WriteString(` _, err = f.WriteString(`
core: core:
noPublish: false noPublish: false
featureSources: ["memory", "storage"]
sources: ["system"] sources: ["system"]
labelWhiteList: "foo" labelWhiteList: "foo"
sleepInterval: "10s" sleepInterval: "10s"
@ -151,6 +156,7 @@ sources:
Convey("specified configuration should take effect", func() { Convey("specified configuration should take effect", func() {
// Verify core config // Verify core config
So(worker.config.Core.NoPublish, ShouldBeFalse) So(worker.config.Core.NoPublish, ShouldBeFalse)
So(worker.config.Core.FeatureSources, ShouldResemble, []string{"memory", "storage"})
So(worker.config.Core.LabelSources, ShouldResemble, []string{"cpu", "kernel", "pci"}) // from cmdline So(worker.config.Core.LabelSources, ShouldResemble, []string{"cpu", "kernel", "pci"}) // from cmdline
So(worker.config.Core.LabelWhiteList.String(), ShouldEqual, "foo") So(worker.config.Core.LabelWhiteList.String(), ShouldEqual, "foo")
So(worker.config.Core.SleepInterval.Duration, ShouldEqual, 10*time.Second) So(worker.config.Core.SleepInterval.Duration, ShouldEqual, 10*time.Second)
@ -173,6 +179,7 @@ sources:
Convey("overrides should take precedence over the config file", func() { Convey("overrides should take precedence over the config file", func() {
// Verify core config // Verify core config
So(worker.config.Core.NoPublish, ShouldBeTrue) So(worker.config.Core.NoPublish, ShouldBeTrue)
So(worker.config.Core.FeatureSources, ShouldResemble, []string{"memory", "storage"})
So(worker.config.Core.LabelSources, ShouldResemble, []string{"fake"}) // from overrides So(worker.config.Core.LabelSources, ShouldResemble, []string{"fake"}) // from overrides
So(worker.config.Core.LabelWhiteList.String(), ShouldEqual, "foo") So(worker.config.Core.LabelWhiteList.String(), ShouldEqual, "foo")
So(worker.config.Core.SleepInterval.Duration, ShouldEqual, 15*time.Second) // from cmdline So(worker.config.Core.SleepInterval.Duration, ShouldEqual, 15*time.Second) // from cmdline
@ -308,13 +315,16 @@ func TestNewNfdWorker(t *testing.T) {
worker := w.(*nfdWorker) worker := w.(*nfdWorker)
So(worker.configure("", ""), ShouldBeNil) So(worker.configure("", ""), ShouldBeNil)
Convey("all 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.enabledSources), ShouldEqual, len(source.GetAllLabelSources())-1) So(len(worker.featureSources), ShouldEqual, len(source.GetAllFeatureSources()))
So(len(worker.labelSources), ShouldEqual, len(source.GetAllLabelSources())-1)
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{Overrides: ConfigOverrideArgs{LabelSources: &utils.StringSliceVal{"fake"}}} args := &Args{Overrides: ConfigOverrideArgs{
LabelSources: &utils.StringSliceVal{"fake"},
FeatureSources: &utils.StringSliceVal{"cpu"}}}
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)
@ -322,8 +332,10 @@ func TestNewNfdWorker(t *testing.T) {
worker := w.(*nfdWorker) worker := w.(*nfdWorker)
So(worker.configure("", ""), ShouldBeNil) So(worker.configure("", ""), ShouldBeNil)
Convey("proper sources should be enabled", func() { Convey("proper sources should be enabled", func() {
So(len(worker.enabledSources), ShouldEqual, 1) So(len(worker.featureSources), ShouldEqual, 1)
So(worker.enabledSources[0].Name(), ShouldEqual, "fake") So(worker.featureSources[0].Name(), ShouldEqual, "cpu")
So(len(worker.labelSources), ShouldEqual, 1)
So(worker.labelSources[0].Name(), ShouldEqual, "fake")
So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp) So(worker.config.Core.LabelWhiteList, ShouldResemble, emptyRegexp)
}) })
}) })
@ -376,12 +388,18 @@ func TestCreateFeatureLabels(t *testing.T) {
func TestAdvertiseFeatureLabels(t *testing.T) { func TestAdvertiseFeatureLabels(t *testing.T) {
Convey("When advertising labels", t, func() { Convey("When advertising labels", t, func() {
w, err := NewNfdWorker(&Args{})
So(err, ShouldBeNil)
worker := w.(*nfdWorker)
mockClient := &labeler.MockLabelerClient{} mockClient := &labeler.MockLabelerClient{}
worker.client = mockClient
labels := map[string]string{"feature-1": "value-1"} labels := map[string]string{"feature-1": "value-1"}
Convey("Correct labeling request is sent", func() { Convey("Correct labeling request is sent", func() {
mockClient.On("SetLabels", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*labeler.SetLabelsRequest")).Return(&labeler.SetLabelsReply{}, nil) mockClient.On("SetLabels", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*labeler.SetLabelsRequest")).Return(&labeler.SetLabelsReply{}, nil)
err := advertiseFeatureLabels(mockClient, labels) err := worker.advertiseFeatureLabels(labels)
Convey("There should be no error", func() { Convey("There should be no error", func() {
So(err, ShouldBeNil) So(err, ShouldBeNil)
}) })
@ -389,7 +407,7 @@ func TestAdvertiseFeatureLabels(t *testing.T) {
Convey("Labeling request fails", func() { Convey("Labeling request fails", func() {
mockErr := errors.New("mock-error") mockErr := errors.New("mock-error")
mockClient.On("SetLabels", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*labeler.SetLabelsRequest")).Return(&labeler.SetLabelsReply{}, mockErr) mockClient.On("SetLabels", mock.AnythingOfType("*context.timerCtx"), mock.AnythingOfType("*labeler.SetLabelsRequest")).Return(&labeler.SetLabelsReply{}, mockErr)
err := advertiseFeatureLabels(mockClient, labels) err := worker.advertiseFeatureLabels(labels)
Convey("An error should be returned", func() { Convey("An error should be returned", func() {
So(err, ShouldEqual, mockErr) So(err, ShouldEqual, mockErr)
}) })

View file

@ -64,6 +64,7 @@ type coreConfig struct {
Klog map[string]string Klog map[string]string
LabelWhiteList utils.RegexpVal LabelWhiteList utils.RegexpVal
NoPublish bool NoPublish bool
FeatureSources []string
Sources *[]string Sources *[]string
LabelSources []string LabelSources []string
SleepInterval duration SleepInterval duration
@ -93,6 +94,7 @@ type ConfigOverrideArgs struct {
// Deprecated // Deprecated
LabelWhiteList *utils.RegexpVal LabelWhiteList *utils.RegexpVal
SleepInterval *time.Duration SleepInterval *time.Duration
FeatureSources *utils.StringSliceVal
LabelSources *utils.StringSliceVal LabelSources *utils.StringSliceVal
} }
@ -105,7 +107,8 @@ type nfdWorker struct {
configFilePath string configFilePath string
config *NFDConfig config *NFDConfig
stop chan struct{} // channel for signaling stop stop chan struct{} // channel for signaling stop
enabledSources []source.LabelSource featureSources []source.FeatureSource
labelSources []source.LabelSource
} }
type duration struct { type duration struct {
@ -139,6 +142,7 @@ func newDefaultConfig() *NFDConfig {
Core: coreConfig{ Core: coreConfig{
LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")}, LabelWhiteList: utils.RegexpVal{Regexp: *regexp.MustCompile("")},
SleepInterval: duration{60 * time.Second}, SleepInterval: duration{60 * time.Second},
FeatureSources: []string{"all"},
LabelSources: []string{"all"}, LabelSources: []string{"all"},
Klog: make(map[string]string), Klog: make(map[string]string),
}, },
@ -178,19 +182,19 @@ func (w *nfdWorker) Run() error {
select { select {
case <-labelTrigger: case <-labelTrigger:
// Run feature discovery // Run feature discovery
for n, s := range source.GetAllFeatureSources() { for _, s := range w.featureSources {
klog.V(2).Infof("running discovery for %q source", n) klog.V(2).Infof("running discovery for %q source", s.Name())
if err := s.Discover(); err != nil { if err := s.Discover(); err != nil {
klog.Errorf("feature discovery of %q source failed: %v", n, err) klog.Errorf("feature discovery of %q source failed: %v", s.Name(), err)
} }
} }
// Get the set of feature labels. // Get the set of feature labels.
labels := createFeatureLabels(w.enabledSources, w.config.Core.LabelWhiteList.Regexp) labels := createFeatureLabels(w.labelSources, w.config.Core.LabelWhiteList.Regexp)
// Update the node with the feature labels. // Update the node with the feature labels.
if w.client != nil { if w.client != nil {
err := advertiseFeatureLabels(w.client, labels) err := w.advertiseFeatureLabels(labels)
if err != nil { if err != nil {
return fmt.Errorf("failed to advertise labels: %s", err.Error()) return fmt.Errorf("failed to advertise labels: %s", err.Error())
} }
@ -294,12 +298,47 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
} }
// Determine enabled feature sources // Determine enabled feature sources
enabled := make(map[string]source.LabelSource) featureSources := make(map[string]source.FeatureSource)
for _, name := range c.FeatureSources {
if name == "all" {
for n, s := range source.GetAllFeatureSources() {
if ts, ok := s.(source.TestSource); !ok || !ts.IsTestSource() {
featureSources[n] = s
}
}
} else {
disable := false
strippedName := name
if strings.HasPrefix(name, "-") {
strippedName = name[1:]
disable = true
}
if s := source.GetFeatureSource(strippedName); s != nil {
if !disable {
featureSources[name] = s
} else {
delete(featureSources, strippedName)
}
} else {
klog.Warningf("skipping unknown feature source %q specified in core.featureSources", name)
}
}
}
w.featureSources = make([]source.FeatureSource, 0, len(featureSources))
for _, s := range featureSources {
w.featureSources = append(w.featureSources, s)
}
sort.Slice(w.featureSources, func(i, j int) bool { return w.featureSources[i].Name() < w.featureSources[j].Name() })
// Determine enabled label sources
labelSources := make(map[string]source.LabelSource)
for _, name := range c.LabelSources { for _, name := range c.LabelSources {
if name == "all" { if name == "all" {
for n, s := range source.GetAllLabelSources() { for n, s := range source.GetAllLabelSources() {
if ts, ok := s.(source.TestSource); !ok || !ts.IsTestSource() { if ts, ok := s.(source.TestSource); !ok || !ts.IsTestSource() {
enabled[n] = s labelSources[n] = s
} }
} }
} else { } else {
@ -311,9 +350,9 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
} }
if s := source.GetLabelSource(strippedName); s != nil { if s := source.GetLabelSource(strippedName); s != nil {
if !disable { if !disable {
enabled[strippedName] = s labelSources[name] = s
} else { } else {
delete(enabled, strippedName) delete(labelSources, strippedName)
} }
} else { } else {
klog.Warningf("skipping unknown source %q specified in core.sources (or -sources)", name) klog.Warningf("skipping unknown source %q specified in core.sources (or -sources)", name)
@ -321,22 +360,28 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
} }
} }
w.enabledSources = make([]source.LabelSource, 0, len(enabled)) w.labelSources = make([]source.LabelSource, 0, len(labelSources))
for _, s := range enabled { for _, s := range labelSources {
w.enabledSources = append(w.enabledSources, s) w.labelSources = append(w.labelSources, s)
} }
sort.Slice(w.enabledSources, func(i, j int) bool { sort.Slice(w.labelSources, func(i, j int) bool {
iP, jP := w.enabledSources[i].Priority(), w.enabledSources[j].Priority() iP, jP := w.labelSources[i].Priority(), w.labelSources[j].Priority()
if iP != jP { if iP != jP {
return iP < jP return iP < jP
} }
return w.enabledSources[i].Name() < w.enabledSources[j].Name() return w.labelSources[i].Name() < w.labelSources[j].Name()
}) })
if klog.V(1).Enabled() { if klog.V(1).Enabled() {
n := make([]string, len(w.enabledSources)) n := make([]string, len(w.featureSources))
for i, s := range w.enabledSources { for i, s := range w.featureSources {
n[i] = s.Name()
}
klog.Infof("enabled feature sources: %s", strings.Join(n, ", "))
n = make([]string, len(w.labelSources))
for i, s := range w.labelSources {
n[i] = s.Name() n[i] = s.Name()
} }
klog.Infof("enabled label sources: %s", strings.Join(n, ", ")) klog.Infof("enabled label sources: %s", strings.Join(n, ", "))
@ -393,6 +438,9 @@ func (w *nfdWorker) configure(filepath string, overrides string) error {
if w.args.Overrides.SleepInterval != nil { if w.args.Overrides.SleepInterval != nil {
c.Core.SleepInterval = duration{*w.args.Overrides.SleepInterval} c.Core.SleepInterval = duration{*w.args.Overrides.SleepInterval}
} }
if w.args.Overrides.FeatureSources != nil {
c.Core.FeatureSources = *w.args.Overrides.FeatureSources
}
if w.args.Overrides.LabelSources != nil { if w.args.Overrides.LabelSources != nil {
c.Core.LabelSources = *w.args.Overrides.LabelSources c.Core.LabelSources = *w.args.Overrides.LabelSources
} }
@ -510,7 +558,7 @@ func getFeatures() map[string]*feature.DomainFeatures {
// advertiseFeatureLabels advertises the feature labels to a Kubernetes node // advertiseFeatureLabels advertises the feature labels to a Kubernetes node
// via the NFD server. // via the NFD server.
func advertiseFeatureLabels(client pb.LabelerClient, labels Labels) error { func (w *nfdWorker) advertiseFeatureLabels(labels Labels) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
@ -520,7 +568,7 @@ func advertiseFeatureLabels(client pb.LabelerClient, labels Labels) error {
Features: getFeatures(), Features: getFeatures(),
NfdVersion: version.Get(), NfdVersion: version.Get(),
NodeName: nfdclient.NodeName()} NodeName: nfdclient.NodeName()}
_, err := client.SetLabels(ctx, &labelReq) _, err := w.client.SetLabels(ctx, &labelReq)
if err != nil { if err != nil {
klog.Errorf("failed to set node labels: %v", err) klog.Errorf("failed to set node labels: %v", err)
return err return err