@@ -18,6 +18,7 @@ package commands
1818
1919import (
2020 "context"
21+ "strings"
2122
2223 "github.com/urfave/cli/v3"
2324
@@ -33,27 +34,73 @@ import (
3334// and error handling for unsupported hooks.
3435// This allows the same command to be used for the nvidia-cdi-hook and
3536// nvidia-ctk hook commands.
36- func ConfigureCDIHookCommand (logger logger.Interface , cmd * cli.Command ) * cli.Command {
37+ func ConfigureCDIHookCommand (logger logger.Interface , base * cli.Command ) * cli.Command {
3738 // We set the default action for the command to issue a warning and exit
3839 // with no error.
3940 // This means that if an unsupported hook is run, a container will not fail
4041 // to launch. An unsupported hook could be the result of a CDI specification
4142 // referring to a new hook that is not yet supported by an older NVIDIA
4243 // Container Toolkit version or a hook that has been removed in newer
4344 // version.
44- cmd .Action = func (ctx context.Context , cmd * cli.Command ) error {
45+ base .Action = func (ctx context.Context , cmd * cli.Command ) error {
4546 return issueUnsupportedHookWarning (logger , cmd )
4647 }
47- // Define the subcommands
48- cmd .Commands = []* cli.Command {
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 {
4988 ldcache .NewCommand (logger ),
5089 symlinks .NewCommand (logger ),
5190 chmod .NewCommand (logger ),
5291 cudacompat .NewCommand (logger ),
5392 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+ },
54101 }
55102
56- return cmd
103+ return base
57104}
58105
59106// issueUnsupportedHookWarning logs a warning that no hook or an unsupported
0 commit comments