Skip to content

Commit 75a30af

Browse files
committed
Remove positional arguments from nvidia-ctk-installer
Parsing positional arguments require additional processing instead of relying on named flags. This change switches to using a named flag for specifying the toolkit installation directory. Signed-off-by: Evan Lezar <[email protected]>
1 parent 89b99ff commit 75a30af

File tree

2 files changed

+24
-120
lines changed

2 files changed

+24
-120
lines changed

cmd/nvidia-ctk-installer/main.go

+22-57
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"os"
66
"os/signal"
77
"path/filepath"
8-
"strings"
98
"syscall"
109

1110
"github.com/urfave/cli/v2"
@@ -20,7 +19,9 @@ import (
2019
const (
2120
toolkitPidFilename = "toolkit.pid"
2221
defaultPidFile = "/run/nvidia/toolkit/" + toolkitPidFilename
23-
toolkitSubDir = "toolkit"
22+
23+
defaultToolkitInstallDir = "/usr/local/nvidia"
24+
toolkitSubDir = "toolkit"
2425

2526
defaultRuntime = "docker"
2627
)
@@ -33,9 +34,10 @@ var signalReceived = make(chan bool, 1)
3334

3435
// options stores the command line arguments
3536
type options struct {
37+
toolkitInstallDir string
38+
3639
noDaemon bool
3740
runtime string
38-
root string
3941
pidFile string
4042
sourceRoot string
4143

@@ -44,24 +46,17 @@ type options struct {
4446
}
4547

4648
func (o options) toolkitRoot() string {
47-
return filepath.Join(o.root, toolkitSubDir)
49+
return filepath.Join(o.toolkitInstallDir, toolkitSubDir)
4850
}
4951

5052
func main() {
5153
logger := logger.New()
52-
53-
remainingArgs, root, err := ParseArgs(logger, os.Args)
54-
if err != nil {
55-
logger.Errorf("Error: unable to parse arguments: %v", err)
56-
os.Exit(1)
57-
}
58-
59-
c := NewApp(logger, root)
54+
c := NewApp(logger)
6055

6156
// Run the CLI
6257
logger.Infof("Starting %v", c.Name)
63-
if err := c.Run(remainingArgs); err != nil {
64-
logger.Errorf("error running nvidia-toolkit: %v", err)
58+
if err := c.Run(os.Args); err != nil {
59+
logger.Errorf("error running %v: %v", c.Name, err)
6560
os.Exit(1)
6661
}
6762

@@ -71,18 +66,14 @@ func main() {
7166
// An app represents the nvidia-ctk-installer.
7267
type app struct {
7368
logger logger.Interface
74-
// defaultRoot stores the root to use if the --root flag is not specified.
75-
defaultRoot string
7669

7770
toolkit *toolkit.Installer
7871
}
7972

8073
// NewApp creates the CLI app fro the specified options.
81-
// defaultRoot is used as the root if not specified via the --root flag.
82-
func NewApp(logger logger.Interface, defaultRoot string) *cli.App {
74+
func NewApp(logger logger.Interface) *cli.App {
8375
a := app{
84-
logger: logger,
85-
defaultRoot: defaultRoot,
76+
logger: logger,
8677
}
8778
return a.build()
8879
}
@@ -94,9 +85,7 @@ func (a app) build() *cli.App {
9485
// Create the top-level CLI
9586
c := cli.NewApp()
9687
c.Name = "nvidia-ctk-installer"
97-
c.Usage = "Install the nvidia-container-toolkit for use by a given runtime"
98-
c.UsageText = "[DESTINATION] [-n | --no-daemon] [-r | --runtime] [-u | --runtime-args]"
99-
c.Description = "DESTINATION points to the host path underneath which the nvidia-container-toolkit should be installed.\nIt will be installed at ${DESTINATION}/toolkit"
88+
c.Usage = "Install the NVIDIA Container Toolkit and configure the specified runtime to use the `nvidia` runtime."
10089
c.Version = info.GetVersionString()
10190
c.Before = func(ctx *cli.Context) error {
10291
return a.Before(ctx, &options)
@@ -123,11 +112,15 @@ func (a app) build() *cli.App {
123112
EnvVars: []string{"RUNTIME"},
124113
},
125114
&cli.StringFlag{
126-
Name: "root",
127-
Value: a.defaultRoot,
128-
Usage: "the folder where the NVIDIA Container Toolkit is to be installed. It will be installed to `ROOT`/toolkit",
129-
Destination: &options.root,
130-
EnvVars: []string{"ROOT"},
115+
Name: "toolkit-install-dir",
116+
Aliases: []string{"root"},
117+
Usage: "The directory where the NVIDIA Container Toolkit is to be installed. " +
118+
"The components of the toolkit will be installed to `ROOT`/toolkit. " +
119+
"Note that in the case of a containerized installer, this is the path in the container and it is " +
120+
"recommended that this match the path on the host.",
121+
Value: defaultToolkitInstallDir,
122+
Destination: &options.toolkitInstallDir,
123+
EnvVars: []string{"TOOLKIT_INSTALL_DIR", "ROOT"},
131124
},
132125
&cli.StringFlag{
133126
Name: "source-root",
@@ -161,7 +154,7 @@ func (a *app) Before(c *cli.Context, o *options) error {
161154
}
162155

163156
func (a *app) validateFlags(c *cli.Context, o *options) error {
164-
if o.root == "" {
157+
if o.toolkitInstallDir == "" {
165158
return fmt.Errorf("the install root must be specified")
166159
}
167160
if _, exists := availableRuntimes[o.runtime]; !exists {
@@ -225,34 +218,6 @@ func (a *app) Run(c *cli.Context, o *options) error {
225218
return nil
226219
}
227220

228-
// ParseArgs checks if a single positional argument was defined and extracts this the root.
229-
// If no positional arguments are defined, it is assumed that the root is specified as a flag.
230-
func ParseArgs(logger logger.Interface, args []string) ([]string, string, error) {
231-
logger.Infof("Parsing arguments")
232-
233-
if len(args) < 2 {
234-
return args, "", nil
235-
}
236-
237-
var lastPositionalArg int
238-
for i, arg := range args {
239-
if strings.HasPrefix(arg, "-") {
240-
break
241-
}
242-
lastPositionalArg = i
243-
}
244-
245-
if lastPositionalArg == 0 {
246-
return args, "", nil
247-
}
248-
249-
if lastPositionalArg == 1 {
250-
return append([]string{args[0]}, args[2:]...), args[1], nil
251-
}
252-
253-
return nil, "", fmt.Errorf("unexpected positional argument(s) %v", args[2:lastPositionalArg+1])
254-
}
255-
256221
func (a *app) initialize(pidFile string) error {
257222
a.logger.Infof("Initializing")
258223

cmd/nvidia-ctk-installer/main_test.go

+2-63
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package main
1818

1919
import (
20-
"fmt"
2120
"os"
2221
"path/filepath"
2322
"strings"
@@ -29,67 +28,6 @@ import (
2928
"github.com/NVIDIA/nvidia-container-toolkit/internal/test"
3029
)
3130

32-
func TestParseArgs(t *testing.T) {
33-
logger, _ := testlog.NewNullLogger()
34-
testCases := []struct {
35-
args []string
36-
expectedRemaining []string
37-
expectedRoot string
38-
expectedError error
39-
}{
40-
{
41-
args: []string{},
42-
expectedRemaining: []string{},
43-
expectedRoot: "",
44-
expectedError: nil,
45-
},
46-
{
47-
args: []string{"app"},
48-
expectedRemaining: []string{"app"},
49-
},
50-
{
51-
args: []string{"app", "root"},
52-
expectedRemaining: []string{"app"},
53-
expectedRoot: "root",
54-
},
55-
{
56-
args: []string{"app", "--flag"},
57-
expectedRemaining: []string{"app", "--flag"},
58-
},
59-
{
60-
args: []string{"app", "root", "--flag"},
61-
expectedRemaining: []string{"app", "--flag"},
62-
expectedRoot: "root",
63-
},
64-
{
65-
args: []string{"app", "root", "not-root", "--flag"},
66-
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root]"),
67-
},
68-
{
69-
args: []string{"app", "root", "not-root"},
70-
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root]"),
71-
},
72-
{
73-
args: []string{"app", "root", "not-root", "also"},
74-
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root also]"),
75-
},
76-
}
77-
78-
for i, tc := range testCases {
79-
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
80-
remaining, root, err := ParseArgs(logger, tc.args)
81-
if tc.expectedError != nil {
82-
require.EqualError(t, err, tc.expectedError.Error())
83-
} else {
84-
require.NoError(t, err)
85-
}
86-
87-
require.ElementsMatch(t, tc.expectedRemaining, remaining)
88-
require.Equal(t, tc.expectedRoot, root)
89-
})
90-
}
91-
}
92-
9331
func TestApp(t *testing.T) {
9432
t.Setenv("__NVCT_TESTING_DEVICES_ARE_FILES", "true")
9533
logger, _ := testlog.NewNullLogger()
@@ -468,10 +406,11 @@ swarm-resource = ""
468406
toolkitRoot := filepath.Join(testRoot, "toolkit-test")
469407
toolkitConfigFile := filepath.Join(toolkitRoot, "toolkit/.config/nvidia-container-runtime/config.toml")
470408

471-
app := NewApp(logger, toolkitRoot)
409+
app := NewApp(logger)
472410

473411
testArgs := []string{
474412
"nvidia-ctk-installer",
413+
"--toolkit-install-dir=" + toolkitRoot,
475414
"--no-daemon",
476415
"--cdi-output-dir=" + cdiOutputDir,
477416
"--config=" + runtimeConfigFile,

0 commit comments

Comments
 (0)