diff --git a/cmd/nvidia-ctk-installer/main.go b/cmd/nvidia-ctk-installer/main.go index d42b524e..0f2f1eb9 100644 --- a/cmd/nvidia-ctk-installer/main.go +++ b/cmd/nvidia-ctk-installer/main.go @@ -38,6 +38,7 @@ type options struct { runtimeArgs string root string pidFile string + sourceRoot string toolkitOptions toolkit.Options runtimeOptions runtime.Options @@ -141,6 +142,13 @@ func (a app) build() *cli.App { Destination: &options.root, EnvVars: []string{"ROOT"}, }, + &cli.StringFlag{ + Name: "source-root", + Value: "/", + Usage: "The folder where the required toolkit artifacts can be found", + Destination: &options.sourceRoot, + EnvVars: []string{"SOURCE_ROOT"}, + }, &cli.StringFlag{ Name: "pid-file", Value: defaultPidFile, @@ -159,6 +167,7 @@ func (a app) build() *cli.App { func (a *app) Before(c *cli.Context, o *options) error { a.toolkit = toolkit.NewInstaller( toolkit.WithLogger(a.logger), + toolkit.WithSourceRoot(o.sourceRoot), toolkit.WithToolkitRoot(o.toolkitRoot()), ) return a.validateFlags(c, o) diff --git a/cmd/nvidia-ctk-installer/main_test.go b/cmd/nvidia-ctk-installer/main_test.go index f7ba5866..c9b1dfdd 100644 --- a/cmd/nvidia-ctk-installer/main_test.go +++ b/cmd/nvidia-ctk-installer/main_test.go @@ -18,10 +18,15 @@ package main import ( "fmt" + "os" + "path/filepath" + "strings" "testing" testlog "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/require" + + "github.com/NVIDIA/nvidia-container-toolkit/internal/test" ) func TestParseArgs(t *testing.T) { @@ -84,3 +89,118 @@ func TestParseArgs(t *testing.T) { }) } } + +func TestApp(t *testing.T) { + t.Setenv("__NVCT_TESTING_DEVICES_ARE_FILES", "true") + logger, _ := testlog.NewNullLogger() + + moduleRoot, err := test.GetModuleRoot() + require.NoError(t, err) + + artifactRoot := filepath.Join(moduleRoot, "testdata", "installer", "artifacts") + + testCases := []struct { + description string + args []string + expectedToolkitConfig string + expectedRuntimeConfig string + }{ + { + description: "no args", + expectedToolkitConfig: `accept-nvidia-visible-devices-as-volume-mounts = false +accept-nvidia-visible-devices-envvar-when-unprivileged = true +disable-require = false +supported-driver-capabilities = "compat32,compute,display,graphics,ngx,utility,video" +swarm-resource = "" + +[nvidia-container-cli] + debug = "" + environment = [] + ldcache = "" + ldconfig = "@/run/nvidia/driver/sbin/ldconfig" + load-kmods = true + no-cgroups = false + path = "{{ .toolkitRoot }}/toolkit/nvidia-container-cli" + root = "/run/nvidia/driver" + user = "" + +[nvidia-container-runtime] + debug = "/dev/null" + log-level = "info" + mode = "auto" + runtimes = ["docker-runc", "runc", "crun"] + + [nvidia-container-runtime.modes] + + [nvidia-container-runtime.modes.cdi] + annotation-prefixes = ["cdi.k8s.io/"] + default-kind = "nvidia.com/gpu" + spec-dirs = ["/etc/cdi", "/var/run/cdi"] + + [nvidia-container-runtime.modes.csv] + mount-spec-path = "/etc/nvidia-container-runtime/host-files-for-container.d" + +[nvidia-container-runtime-hook] + path = "{{ .toolkitRoot }}/toolkit/nvidia-container-runtime-hook" + skip-mode-detection = true + +[nvidia-ctk] + path = "{{ .toolkitRoot }}/toolkit/nvidia-ctk" +`, + expectedRuntimeConfig: `{ + "default-runtime": "nvidia", + "runtimes": { + "nvidia": { + "args": [], + "path": "{{ .toolkitRoot }}/toolkit/nvidia-container-runtime" + }, + "nvidia-cdi": { + "args": [], + "path": "{{ .toolkitRoot }}/toolkit/nvidia-container-runtime.cdi" + }, + "nvidia-legacy": { + "args": [], + "path": "{{ .toolkitRoot }}/toolkit/nvidia-container-runtime.legacy" + } + } +}`, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + testRoot := t.TempDir() + + runtimeConfigFile := filepath.Join(testRoot, "config.file") + + toolkitRoot := filepath.Join(testRoot, "toolkit-test") + toolkitConfigFile := filepath.Join(toolkitRoot, "toolkit/.config/nvidia-container-runtime/config.toml") + + app := NewApp(logger, toolkitRoot) + + testArgs := []string{ + "nvidia-ctk-installer", + "--no-daemon", + "--pid-file=" + filepath.Join(testRoot, "toolkit.pid"), + "--source-root=" + filepath.Join(artifactRoot, "deb"), + "--config=" + runtimeConfigFile, + "--restart-mode=none", + } + + err := app.Run(append(testArgs, tc.args...)) + + require.NoError(t, err) + + require.FileExists(t, toolkitConfigFile) + toolkitConfigFileContents, err := os.ReadFile(toolkitConfigFile) + require.NoError(t, err) + require.EqualValues(t, strings.ReplaceAll(tc.expectedToolkitConfig, "{{ .toolkitRoot }}", toolkitRoot), string(toolkitConfigFileContents)) + + require.FileExists(t, runtimeConfigFile) + runtimeConfigFileContents, err := os.ReadFile(runtimeConfigFile) + require.NoError(t, err) + require.EqualValues(t, strings.ReplaceAll(tc.expectedRuntimeConfig, "{{ .toolkitRoot }}", toolkitRoot), string(runtimeConfigFileContents)) + }) + } + +}