Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/config/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"io"
"os"

cli "github.com/urfave/cli/v2"
cli "github.com/urfave/cli/v3"
"k8s.io/klog/v2"

"sigs.k8s.io/yaml"
Expand All @@ -42,7 +42,7 @@ type Config struct {
// NewConfig builds out a Config struct from a config file (or command line flags).
// The data stored in the config will be populated in order of precedence from
// (1) command line, (2) environment variable, (3) config file.
func NewConfig(c *cli.Context, flags []cli.Flag) (*Config, error) {
func NewConfig(c *cli.Command, flags []cli.Flag) (*Config, error) {
config := &Config{Version: Version}

if configFile := c.String("config-file"); configFile != "" {
Expand Down
6 changes: 3 additions & 3 deletions api/config/v1/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"encoding/json"
"fmt"

cli "github.com/urfave/cli/v2"
cli "github.com/urfave/cli/v3"
)

// prt returns a reference to whatever type is passed into it
Expand All @@ -29,7 +29,7 @@ func ptr[T any](x T) *T {
}

// updateFromCLIFlag conditionally updates the config flag at 'pflag' to the value of the CLI flag with name 'flagName'
func updateFromCLIFlag[T any](pflag **T, c *cli.Context, flagName string) {
func updateFromCLIFlag[T any](pflag **T, c *cli.Command, flagName string) {
if c.IsSet(flagName) || *pflag == (*T)(nil) {
switch flag := any(pflag).(type) {
case **string:
Expand Down Expand Up @@ -112,7 +112,7 @@ type GFDCommandLineFlags struct {
}

// UpdateFromCLIFlags updates Flags from settings in the cli Flags if they are set.
func (f *Flags) UpdateFromCLIFlags(c *cli.Context, flags []cli.Flag) {
func (f *Flags) UpdateFromCLIFlags(c *cli.Command, flags []cli.Flag) {
for _, flag := range flags {
for _, n := range flag.Names() {
// Common flags
Expand Down
47 changes: 24 additions & 23 deletions cmd/config-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package main

import (
"context"
"fmt"
"os"
"path/filepath"
Expand All @@ -25,7 +26,7 @@ import (
"syscall"

"github.com/prometheus/procfs"
cli "github.com/urfave/cli/v2"
cli "github.com/urfave/cli/v3"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/fields"
Expand Down Expand Up @@ -68,7 +69,7 @@ type Flags struct {
ConfigFileSrcdir string
ConfigFileDst string
DefaultConfig string
FallbackStrategies cli.StringSlice
FallbackStrategies []string
SendSignal bool
Signal int
ProcessToSignal string
Expand Down Expand Up @@ -116,12 +117,12 @@ func (m *SyncableConfig) Get() string {
func main() {
flags := Flags{}

c := cli.NewApp()
c.Before = func(c *cli.Context) error {
return validateFlags(c, &flags)
c := cli.Command{}
c.Before = func(ctx context.Context, cmd *cli.Command) (context.Context, error) {
return ctx, validateFlags(cmd, &flags)
}
c.Action = func(c *cli.Context) error {
return start(c, &flags)
c.Action = func(_ context.Context, cmd *cli.Command) error {
return start(cmd, &flags)
}

c.Flags = []cli.Flag{
Expand All @@ -130,87 +131,87 @@ func main() {
Value: DefaultOneshot,
Usage: "check and update the config only once and then exit",
Destination: &flags.Oneshot,
EnvVars: []string{"ONESHOT"},
Sources: cli.EnvVars("ONESHOT"),
},
&cli.StringFlag{
Name: "kubeconfig",
Value: "",
Usage: "absolute path to the kubeconfig file",
Destination: &flags.Kubeconfig,
EnvVars: []string{"KUBECONFIG"},
Sources: cli.EnvVars("KUBECONFIG"),
},
&cli.StringFlag{
Name: "node-name",
Value: "",
Usage: "the name of the node to watch for label changes on",
Destination: &flags.NodeName,
EnvVars: []string{"NODE_NAME"},
Sources: cli.EnvVars("NODE_NAME"),
},
&cli.StringFlag{
Name: "node-label",
Value: DefaultConfigLabel,
Usage: "the name of the node label to use for selecting a config",
Destination: &flags.NodeLabel,
EnvVars: []string{"NODE_LABEL"},
Sources: cli.EnvVars("NODE_LABEL"),
},
&cli.StringFlag{
Name: "config-file-srcdir",
Value: "",
Usage: "the path to the directory containing available device configuration files",
Destination: &flags.ConfigFileSrcdir,
EnvVars: []string{"CONFIG_FILE_SRCDIR"},
Sources: cli.EnvVars("CONFIG_FILE_SRCDIR"),
},
&cli.StringFlag{
Name: "config-file-dst",
Value: "",
Usage: "the path to destination device configuration file",
Destination: &flags.ConfigFileDst,
EnvVars: []string{"CONFIG_FILE_DST"},
Sources: cli.EnvVars("CONFIG_FILE_DST"),
},
&cli.StringFlag{
Name: "default-config",
Value: "",
Usage: "the default config to use if no label is set",
Destination: &flags.DefaultConfig,
EnvVars: []string{"DEFAULT_CONFIG"},
Sources: cli.EnvVars("DEFAULT_CONFIG"),
},
&cli.StringSliceFlag{
Name: "fallback-strategies",
Usage: "ordered list of fallback strategies to use to set a default config when none is provided",
Destination: &flags.FallbackStrategies,
EnvVars: []string{"FALLBACK_STRATEGIES"},
Sources: cli.EnvVars("FALLBACK_STRATEGIES"),
},
&cli.BoolFlag{
Name: "send-signal",
Value: DefaultSendSignal,
Usage: "send a signal to <process-to-signal> once a config change is made",
Destination: &flags.SendSignal,
EnvVars: []string{"SEND_SIGNAL"},
Sources: cli.EnvVars("SEND_SIGNAL"),
},
&cli.IntFlag{
Name: "signal",
Value: DefaultSignal,
Usage: "the signal to sent to <process-to-signal> if <send-signal> is set",
Destination: &flags.Signal,
EnvVars: []string{"SIGNAL"},
Sources: cli.EnvVars("SIGNAL"),
},
&cli.StringFlag{
Name: "process-to-signal",
Value: DefaultProcessToSignal,
Usage: "the name of the process to signal if <send-signal> is set",
Destination: &flags.ProcessToSignal,
EnvVars: []string{"PROCESS_TO_SIGNAL"},
Sources: cli.EnvVars("PROCESS_TO_SIGNAL"),
},
}

err := c.Run(os.Args)
err := c.Run(context.Background(), os.Args)
if err != nil {
klog.Error(err)
os.Exit(1)
}
}

func validateFlags(c *cli.Context, f *Flags) error {
func validateFlags(c *cli.Command, f *Flags) error {
if f.NodeName == "" {
return fmt.Errorf("invalid <node-name>: must not be empty string")
}
Expand All @@ -226,7 +227,7 @@ func validateFlags(c *cli.Context, f *Flags) error {
return nil
}

func start(c *cli.Context, f *Flags) error {
func start(c *cli.Command, f *Flags) error {
kubeconfig, err := clientcmd.BuildConfigFromFlags("", f.Kubeconfig)
if err != nil {
return fmt.Errorf("error building kubernetes clientcmd config: %s", err)
Expand Down Expand Up @@ -365,8 +366,8 @@ func updateConfigName(config string, f *Flags) (string, error) {
}

// Otherwise, if no explicit default is set, step through the configured fallbacks.
klog.Infof("No value set and no default set. Attempting fallback strategies: %v", f.FallbackStrategies.Value())
for _, fallback := range f.FallbackStrategies.Value() {
klog.Infof("No value set and no default set. Attempting fallback strategies: %v", f.FallbackStrategies)
for _, fallback := range f.FallbackStrategies {
switch fallback {
case FallbackStrategyNamedConfig:
klog.Infof("Attempting to find config named: %v", NamedConfigFallback)
Expand Down
37 changes: 19 additions & 18 deletions cmd/gpu-feature-discovery/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
package main

import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"syscall"
"time"

"github.com/urfave/cli/v2"
"github.com/urfave/cli/v3"
"k8s.io/klog/v2"

"github.com/NVIDIA/go-nvlib/pkg/nvlib/device"
Expand Down Expand Up @@ -40,80 +41,80 @@ type Config struct {
func main() {
config := &Config{}

c := cli.NewApp()
c := cli.Command{}
c.Name = "GPU Feature Discovery"
c.Usage = "generate labels for NVIDIA devices"
c.Version = info.GetVersionString()
c.Action = func(ctx *cli.Context) error {
return start(ctx, config)
c.Action = func(_ context.Context, cmd *cli.Command) error {
return start(cmd, config)
}

config.flags = []cli.Flag{
&cli.StringFlag{
Name: "mig-strategy",
Value: spec.MigStrategyNone,
Usage: "the desired strategy for exposing MIG devices on GPUs that support it:\n\t\t[none | single | mixed]",
EnvVars: []string{"GFD_MIG_STRATEGY", "MIG_STRATEGY"},
Sources: cli.EnvVars("GFD_MIG_STRATEGY", "MIG_STRATEGY"),
},
&cli.BoolFlag{
Name: "fail-on-init-error",
Value: true,
Usage: "fail the plugin if an error is encountered during initialization, otherwise block indefinitely",
EnvVars: []string{"GFD_FAIL_ON_INIT_ERROR", "FAIL_ON_INIT_ERROR"},
Sources: cli.EnvVars("GFD_FAIL_ON_INIT_ERROR", "FAIL_ON_INIT_ERROR"),
},
&cli.BoolFlag{
Name: "oneshot",
Value: false,
Usage: "Label once and exit",
EnvVars: []string{"GFD_ONESHOT"},
Sources: cli.EnvVars("GFD_ONESHOT"),
},
&cli.BoolFlag{
Name: "no-timestamp",
Value: false,
Usage: "Do not add the timestamp to the labels",
EnvVars: []string{"GFD_NO_TIMESTAMP"},
Sources: cli.EnvVars("GFD_NO_TIMESTAMP"),
},
&cli.DurationFlag{
Name: "sleep-interval",
Value: 60 * time.Second,
Usage: "Time to sleep between labeling",
EnvVars: []string{"GFD_SLEEP_INTERVAL"},
Sources: cli.EnvVars("GFD_SLEEP_INTERVAL"),
},
&cli.StringFlag{
Name: "output-file",
Aliases: []string{"output", "o"},
Value: "/etc/kubernetes/node-feature-discovery/features.d/gfd",
EnvVars: []string{"GFD_OUTPUT_FILE"},
Sources: cli.EnvVars("GFD_OUTPUT_FILE"),
},
&cli.StringFlag{
Name: "machine-type-file",
Value: "/sys/class/dmi/id/product_name",
Usage: "a path to a file that contains the DMI (SMBIOS) information for the node",
EnvVars: []string{"GFD_MACHINE_TYPE_FILE"},
Sources: cli.EnvVars("GFD_MACHINE_TYPE_FILE"),
},
&cli.StringFlag{
Name: "config-file",
Usage: "the path to a config file as an alternative to command line options or environment variables",
Destination: &config.configFile,
EnvVars: []string{"GFD_CONFIG_FILE", "CONFIG_FILE"},
Sources: cli.EnvVars("GFD_CONFIG_FILE", "CONFIG_FILE"),
},
&cli.BoolFlag{
Name: "use-node-feature-api",
Usage: "Use NFD NodeFeature API to publish labels",
EnvVars: []string{"GFD_USE_NODE_FEATURE_API", "USE_NODE_FEATURE_API"},
Sources: cli.EnvVars("GFD_USE_NODE_FEATURE_API", "USE_NODE_FEATURE_API"),
},
&cli.StringFlag{
Name: "device-discovery-strategy",
Value: "auto",
Usage: "the strategy to use to discover devices: 'auto', 'nvml', 'tegra' or 'vfio'",
EnvVars: []string{"DEVICE_DISCOVERY_STRATEGY"},
Sources: cli.EnvVars("DEVICE_DISCOVERY_STRATEGY"),
},
&cli.StringFlag{
Name: "driver-root-ctr-path",
Aliases: []string{"container-driver-root"},
Value: spec.DefaultContainerDriverRoot,
Usage: "the path where the NVIDIA driver root is mounted in the container",
EnvVars: []string{"DRIVER_ROOT_CTR_PATH", "CONTAINER_DRIVER_ROOT"},
Sources: cli.EnvVars("DRIVER_ROOT_CTR_PATH", "CONTAINER_DRIVER_ROOT"),
},
}

Expand All @@ -122,7 +123,7 @@ func main() {

c.Flags = config.flags

if err := c.Run(os.Args); err != nil {
if err := c.Run(context.Background(), os.Args); err != nil {
klog.Error(err)
os.Exit(1)
}
Expand All @@ -141,7 +142,7 @@ func validateFlags(config *spec.Config) error {
}

// loadConfig loads the config from the spec file.
func (cfg *Config) loadConfig(c *cli.Context) (*spec.Config, error) {
func (cfg *Config) loadConfig(c *cli.Command) (*spec.Config, error) {
config, err := spec.NewConfig(c, cfg.flags)
if err != nil {
return nil, fmt.Errorf("unable to finalize config: %v", err)
Expand All @@ -154,7 +155,7 @@ func (cfg *Config) loadConfig(c *cli.Context) (*spec.Config, error) {
return config, nil
}

func start(c *cli.Context, cfg *Config) error {
func start(c *cli.Command, cfg *Config) error {
defer func() {
klog.Info("Exiting")
}()
Expand Down
Loading