Skip to content

Commit 6cb8333

Browse files
committed
feat: add ability to export features for static node
For the HPC use case, we want to be able to export static features to the terminal or JSON path. Signed-off-by: vsoch <[email protected]>
1 parent 310a390 commit 6cb8333

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

cmd/nfd/subcmd/export/export.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package export
18+
19+
import (
20+
"fmt"
21+
"os"
22+
23+
"github.com/spf13/cobra"
24+
)
25+
26+
var ExportCmd = &cobra.Command{
27+
Use: "export",
28+
Short: "Export features commands",
29+
}
30+
31+
func Execute() {
32+
if err := ExportCmd.Execute(); err != nil {
33+
fmt.Println(err)
34+
os.Exit(1)
35+
}
36+
}

cmd/nfd/subcmd/export/features.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package export
18+
19+
import (
20+
"encoding/json"
21+
"fmt"
22+
"os"
23+
24+
"github.com/spf13/cobra"
25+
26+
"sigs.k8s.io/node-feature-discovery/source"
27+
)
28+
29+
var (
30+
outputPath string
31+
)
32+
33+
func NewExportCmd() *cobra.Command {
34+
cmd := &cobra.Command{
35+
Use: "features",
36+
Short: "Export features for given node",
37+
RunE: func(cmd *cobra.Command, args []string) error {
38+
sources := map[string]source.FeatureSource{}
39+
for k, v := range source.GetAllFeatureSources() {
40+
if ts, ok := v.(source.SupplementalSource); ok && ts.DisableByDefault() {
41+
continue
42+
}
43+
sources[k] = v
44+
}
45+
46+
// Discover all feature sources
47+
for _, s := range sources {
48+
if err := s.Discover(); err != nil {
49+
return fmt.Errorf("error during discovery of source %s: %w", s.Name(), err)
50+
}
51+
}
52+
53+
// Make into flat format.
54+
features := source.GetAllFeatures()
55+
featureListing := map[string]string{}
56+
57+
// A flag's presence == true
58+
for flagName := range features.Flags {
59+
featureListing[flagName] = "true"
60+
}
61+
62+
// Attributes are sets of elements (key value pairs)
63+
for featureName, featureSet := range features.Attributes {
64+
for elementName, elementValue := range featureSet.Elements {
65+
featureListing[fmt.Sprintf("%s.%s", featureName, elementName)] = elementValue
66+
}
67+
}
68+
69+
for featureName, featureSet := range features.Instances {
70+
for i, element := range featureSet.Elements {
71+
for attrName, attrValue := range element.Attributes {
72+
featureListing[fmt.Sprintf("%s.%d.%s", featureName, i, attrName)] = attrValue
73+
}
74+
}
75+
}
76+
exportedLabels, err := json.MarshalIndent(featureListing, "", " ")
77+
if err != nil {
78+
return err
79+
}
80+
81+
if outputPath != "" {
82+
fd, err := os.Create(outputPath)
83+
if err != nil {
84+
return err
85+
}
86+
defer fd.Close()
87+
_, err = fmt.Fprint(fd, string(exportedLabels))
88+
return err
89+
} else {
90+
fmt.Println(string(exportedLabels))
91+
}
92+
return nil
93+
},
94+
}
95+
cmd.Flags().StringVar(&outputPath, "path", "", "export to this JSON path")
96+
return cmd
97+
}
98+
99+
func init() {
100+
ExportCmd.AddCommand(NewExportCmd())
101+
}

cmd/nfd/subcmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/spf13/cobra"
2424

2525
"sigs.k8s.io/node-feature-discovery/cmd/nfd/subcmd/compat"
26+
"sigs.k8s.io/node-feature-discovery/cmd/nfd/subcmd/export"
2627
)
2728

2829
// RootCmd represents the base command when called without any subcommands
@@ -33,6 +34,7 @@ var RootCmd = &cobra.Command{
3334

3435
func init() {
3536
RootCmd.AddCommand(compat.CompatCmd)
37+
RootCmd.AddCommand(export.ExportCmd)
3638
}
3739

3840
// Execute adds all child commands to the root command and sets flags appropriately.

docs/usage/nfd-export.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
title: "Feature Export"
3+
layout: default
4+
sort: 12
5+
---
6+
7+
# Feature Export
8+
{: .no_toc}
9+
10+
## Table of contents
11+
{: .no_toc .text-delta}
12+
13+
1. TOC
14+
{:toc}
15+
16+
---
17+
18+
## Feature Export
19+
20+
**Feature export is in the experimental `v1alpha1` version.**
21+
22+
If you are interested in exporting features in a generic context, the nfd client supports an export mode, where features can be derived without requiring a Kubernetes context.
23+
This addresses use cases such as high performance computing (HPC) and other environments with compute nodes that warrant assessment, but may not have Kubernetes running, or may not be able to or want to run a central daemon service for data.
24+
To use export, you can use `nfd export features`:
25+
26+
```bash
27+
nfd export features
28+
```
29+
30+
By default, JSON structure with parsed key value pairs will appear in the terminal.
31+
To save to a file path:
32+
33+
```bash
34+
nfd export features --path features.json
35+
```

0 commit comments

Comments
 (0)