1717package commands
1818
1919import (
20+ "context"
21+ "strings"
22+
2023 "github.com/urfave/cli/v3"
2124
2225 "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/chmod"
@@ -27,27 +30,89 @@ import (
2730 "github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
2831)
2932
30- // New creates the commands associated with supported CDI hooks.
31- // These are shared by the nvidia-cdi-hook and nvidia-ctk hook commands.
32- func New (logger logger.Interface ) []* cli.Command {
33- return []* cli.Command {
33+ // ConfigureCDIHookCommand configures a base command with supported CDI hooks
34+ // and error handling for unsupported hooks.
35+ // This allows the same command to be used for the nvidia-cdi-hook and
36+ // nvidia-ctk hook commands.
37+ func ConfigureCDIHookCommand (logger logger.Interface , base * cli.Command ) * cli.Command {
38+ // We set the default action for the command to issue a warning and exit
39+ // with no error.
40+ // This means that if an unsupported hook is run, a container will not fail
41+ // to launch. An unsupported hook could be the result of a CDI specification
42+ // referring to a new hook that is not yet supported by an older NVIDIA
43+ // Container Toolkit version or a hook that has been removed in newer
44+ // version.
45+ base .Action = func (ctx context.Context , cmd * cli.Command ) error {
46+ return issueUnsupportedHookWarning (logger , cmd )
47+ }
48+ // CommandNotFound is triggered when an unrecognised (sub)command is detected.
49+ // We assume that an unrecognised (sub)command represents an unsupported hook
50+ // (usually a hook that was added or removed)
51+ base .CommandNotFound = func (ctx context.Context , cmd * cli.Command , commandName string ) {
52+ _ = issueUnsupportedHookWarning (logger , cmd )
53+ }
54+ // OnUsageError is triggered when an unexpected flag is detected.
55+ // We check the invoked command to determine whether it is an expected
56+ // hook, and assume that this is an unsupported hook otherwise.
57+ base .OnUsageError = func (ctx context.Context , cmd * cli.Command , err error , isSubcommand bool ) error {
58+ // If this is not an error that comes from parsing an unrecognised flag,
59+ // return it as is.
60+ if ! strings .HasPrefix (err .Error (), "flag provided but not defined: -" ) {
61+ return err
62+ }
63+
64+ // If the first argument is a recognised command, we return the error as
65+ // is since it represents an incorrect argument to the specific hook.
66+ var subcommandName string
67+ for _ , arg := range cmd .Args ().Slice () {
68+ if strings .HasPrefix (arg , "-" ) {
69+ continue
70+ }
71+ subcommandName = arg
72+ break
73+ }
74+ // If a subcommand is detected and is a recognised subcommand, we return
75+ // the error as is.
76+ if subcommandName != "" && cmd .Command (subcommandName ) != nil {
77+ return err
78+ }
79+
80+ // At this point either no args have been supplied or the (sub)command
81+ // (first arg) is not regognised.
82+ // We issue a warning and returun nil.
83+ return issueUnsupportedHookWarning (logger , cmd )
84+ }
85+
86+ // Define the supported hooks.
87+ base .Commands = []* cli.Command {
3488 ldcache .NewCommand (logger ),
3589 symlinks .NewCommand (logger ),
3690 chmod .NewCommand (logger ),
3791 cudacompat .NewCommand (logger ),
3892 disabledevicenodemodification .NewCommand (logger ),
93+ {
94+ Name : "noop" ,
95+ Usage : "The noop hook performs no actions and is only added to facilitate basic testing of the CLI" ,
96+ Hidden : true ,
97+ Action : func (_ context.Context , _ * cli.Command ) error {
98+ return nil
99+ },
100+ },
39101 }
102+
103+ return base
40104}
41105
42- // IssueUnsupportedHookWarning logs a warning that no hook or an unsupported
106+ // issueUnsupportedHookWarning logs a warning that no hook or an unsupported
43107// hook has been specified.
44108// This happens if a subcommand is provided that does not match one of the
45109// subcommands that has been explicitly specified.
46- func IssueUnsupportedHookWarning (logger logger.Interface , c * cli.Command ) {
110+ func issueUnsupportedHookWarning (logger logger.Interface , c * cli.Command ) error {
47111 args := c .Args ().Slice ()
48112 if len (args ) == 0 {
49113 logger .Warningf ("No CDI hook specified" )
50114 } else {
51115 logger .Warningf ("Unsupported CDI hook: %v" , args [0 ])
52116 }
117+ return nil
53118}
0 commit comments