diff --git a/cmd/nvidia-ctk-installer/container/container.go b/cmd/nvidia-ctk-installer/container/container.go index 07fd9d589..80e2d1f6f 100644 --- a/cmd/nvidia-ctk-installer/container/container.go +++ b/cmd/nvidia-ctk-installer/container/container.go @@ -36,9 +36,9 @@ const ( // Options defines the shared options for the CLIs to configure containers runtimes. type Options struct { DropInConfig string - // TODO: Rename to TopLevelConfig - Config string - Socket string + // TopLevelConfigPath stores the path to the top-level config for the runtime. + TopLevelConfigPath string + Socket string // ExecutablePath specifies the path to the container runtime executable. // This is used to extract the current config, for example. // If a HostRootMount is specified, this path is relative to the host root @@ -75,7 +75,7 @@ func (o Options) Unconfigure(cfg engine.Interface) error { func (o Options) flush(cfg engine.Interface) error { filepath := o.DropInConfig if filepath == "" { - filepath = o.Config + filepath = o.TopLevelConfigPath } logrus.Infof("Flushing config to %v", filepath) n, err := cfg.Save(filepath) diff --git a/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go b/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go index 83afb0a98..15d5c0472 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go +++ b/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go @@ -51,19 +51,19 @@ func TestContainerdConfigLifecycle(t *testing.T) { { description: "v1: existing config without nvidia runtime", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - EnableCDI: true, - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + EnableCDI: true, + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial v1 config initialConfig := `version = 1 @@ -80,13 +80,13 @@ func TestContainerdConfigLifecycle(t *testing.T) { [plugins.cri.containerd.runtimes.runc.options] Runtime = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `version = 1 @@ -132,9 +132,9 @@ func TestContainerdConfigLifecycle(t *testing.T) { return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `version = 1 @@ -162,18 +162,18 @@ func TestContainerdConfigLifecycle(t *testing.T) { { description: "v1: existing config with default_runtime_name and OPTIONS inheritance", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial v1 config without a default runtime set // This tests OPTIONS inheritance from an existing runtime @@ -193,13 +193,13 @@ func TestContainerdConfigLifecycle(t *testing.T) { SystemdCgroup = true NoPivotRoot = false ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `version = 1 @@ -260,9 +260,9 @@ func TestContainerdConfigLifecycle(t *testing.T) { return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `version = 1 @@ -292,18 +292,18 @@ func TestContainerdConfigLifecycle(t *testing.T) { { description: "v1: OPTIONS inheritance from default runtime specified by default_runtime_name", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, // Don't change the default runtime - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, // Don't change the default runtime + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Create config with default_runtime_name pointing to custom runtime // This tests that OPTIONS are inherited from the default runtime @@ -332,13 +332,13 @@ func TestContainerdConfigLifecycle(t *testing.T) { [plugins.cri.containerd.runtimes.runc.options] Runtime = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // Verify that nvidia runtimes inherit OPTIONS from the default runtime (custom) @@ -410,9 +410,9 @@ func TestContainerdConfigLifecycle(t *testing.T) { return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // After cleanup, should return to original state @@ -451,18 +451,18 @@ func TestContainerdConfigLifecycle(t *testing.T) { { description: "v1: existing config with default_runtime_name set and restoration on cleanup", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial v1 config with default_runtime_name set to "runc" initialConfig := `version = 1 @@ -479,13 +479,13 @@ func TestContainerdConfigLifecycle(t *testing.T) { [plugins.cri.containerd.runtimes.runc.options] Runtime = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `version = 1 @@ -530,9 +530,9 @@ func TestContainerdConfigLifecycle(t *testing.T) { return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // Current implementation limitation: default_runtime_name is deleted entirely @@ -561,21 +561,21 @@ func TestContainerdConfigLifecycle(t *testing.T) { { description: "v2: top-level config does not exist", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -629,7 +629,7 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.NoFileExists(t, co.Config) + require.NoFileExists(t, co.TopLevelConfigPath) require.NoFileExists(t, co.DropInConfig) return nil }, @@ -637,20 +637,20 @@ version = 2 { description: "v2: existing config without nvidia runtime and CDI enabled", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - EnableCDI: true, - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + EnableCDI: true, + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial config initialConfig := `version = 2 @@ -667,13 +667,13 @@ version = 2 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] BinaryName = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -736,9 +736,9 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // TODO: What is the expectation here? Do we expect that the imports \ @@ -773,19 +773,19 @@ version = 2 { description: "v2: existing config with nvidia runtime using old path already present", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) initialConfig := `version = 2 @@ -807,13 +807,13 @@ version = 2 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] BinaryName = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -881,10 +881,10 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) // If file exists, verify nvidia runtimes were removed - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // TODO: Do we expect that the default_runtime = nvidia be removed? @@ -917,21 +917,21 @@ version = 2 { description: "v2: complex config with multiple plugins and settings", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - EnableCDI: true, - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + EnableCDI: true, + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", ContainerRuntimeModesCDIAnnotationPrefixes: []string{"cdi.k8s.io"}, }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial complex config initialConfig := `version = 2 @@ -966,13 +966,13 @@ state = "/run/containerd" [plugins."io.containerd.internal.v1.opt"] path = "/opt/containerd" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1059,9 +1059,9 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1112,19 +1112,19 @@ version = 2 { description: "v2: existing config without default runtime (SetAsDefault=false)", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial config without any default runtime initialConfig := `version = 2 @@ -1140,13 +1140,13 @@ version = 2 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] BinaryName = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1207,9 +1207,9 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1239,19 +1239,19 @@ version = 2 { description: "v2: existing config without default runtime (SetAsDefault=true)", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial config without any default runtime initialConfig := `version = 2 @@ -1267,13 +1267,13 @@ version = 2 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] BinaryName = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1334,9 +1334,9 @@ version = 2 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // TODO: Add test where imports are already specified. @@ -1368,19 +1368,19 @@ version = 2 { description: "v3: minimal config without nvidia runtime", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write v3 config with runc runtime initialConfig := `version = 3 @@ -1395,13 +1395,13 @@ version = 2 [plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc.options] BinaryName = "/usr/bin/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1461,9 +1461,9 @@ version = 3 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // Should return to original v3 config with just runc @@ -1494,19 +1494,19 @@ version = 3 { description: "v3: existing config with runtime and OPTIONS inheritance", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/containerd/config.toml", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", - ExecutablePath: "not-containerd", + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", + ExecutablePath: "not-containerd", }, options: Options{ runtimeType: "io.containerd.runc.v2", }, prepareEnvironment: func(t *testing.T, co *container.Options, o *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) // Write initial v3 config with a runtime that has custom OPTIONS initialConfig := `version = 3 @@ -1526,13 +1526,13 @@ version = 3 NoPivotRoot = false Root = "/run/containerd/runc" ` - require.NoError(t, os.WriteFile(co.Config, []byte(initialConfig), 0600)) + require.NoError(t, os.WriteFile(co.TopLevelConfigPath, []byte(initialConfig), 0600)) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `imports = ["` + filepath.Dir(co.DropInConfig) + `/*.toml"] @@ -1606,9 +1606,9 @@ version = 3 return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // After cleanup, should return to original state @@ -1648,7 +1648,7 @@ version = 3 testRoot := t.TempDir() // Update paths - tc.containerOptions.Config = strings.ReplaceAll(tc.containerOptions.Config, "{{ .testRoot }}", testRoot) + tc.containerOptions.TopLevelConfigPath = strings.ReplaceAll(tc.containerOptions.TopLevelConfigPath, "{{ .testRoot }}", testRoot) tc.containerOptions.DropInConfig = strings.ReplaceAll(tc.containerOptions.DropInConfig, "{{ .testRoot }}", testRoot) tc.containerOptions.RuntimeDir = strings.ReplaceAll(tc.containerOptions.RuntimeDir, "{{ .testRoot }}", testRoot) diff --git a/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go b/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go index a63b9d6aa..46b821a9c 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go +++ b/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go @@ -172,11 +172,11 @@ func GetLowlevelRuntimePaths(o *container.Options, co *Options) ([]string, error func getRuntimeConfig(o *container.Options, co *Options) (engine.Interface, error) { return containerd.New( - containerd.WithTopLevelConfigPath(o.Config), + containerd.WithTopLevelConfigPath(o.TopLevelConfigPath), containerd.WithConfigSource( toml.LoadFirst( containerd.CommandLineSource(o.HostRootMount, o.ExecutablePath), - toml.FromFile(o.Config), + toml.FromFile(o.TopLevelConfigPath), ), ), containerd.WithRuntimeType(co.runtimeType), diff --git a/cmd/nvidia-ctk-installer/container/runtime/crio/config_test.go b/cmd/nvidia-ctk-installer/container/runtime/crio/config_test.go index 5a07cc39c..828a672b2 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/crio/config_test.go +++ b/cmd/nvidia-ctk-installer/container/runtime/crio/config_test.go @@ -47,18 +47,18 @@ func TestCrioConfigLifecycle(t *testing.T) { { description: "config mode: top-level config does not exist", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/crio/crio.conf", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", + TopLevelConfigPath: "{{ .testRoot }}/etc/crio/crio.conf", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", }, options: Options{ configMode: "config", }, assertSetupPostConditions: func(t *testing.T, co *container.Options, _ *Options) error { - require.NoFileExists(t, co.Config) + require.NoFileExists(t, co.TopLevelConfigPath) require.FileExists(t, co.DropInConfig) actual, err := os.ReadFile(co.DropInConfig) @@ -87,7 +87,7 @@ func TestCrioConfigLifecycle(t *testing.T) { return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, _ *Options) error { - require.NoFileExists(t, co.Config) + require.NoFileExists(t, co.TopLevelConfigPath) require.NoFileExists(t, co.DropInConfig) return nil }, @@ -95,18 +95,18 @@ func TestCrioConfigLifecycle(t *testing.T) { { description: "config mode: existing config without nvidia runtime", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/crio/crio.conf", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", + TopLevelConfigPath: "{{ .testRoot }}/etc/crio/crio.conf", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", }, options: Options{ configMode: "config", }, prepareEnvironment: func(t *testing.T, co *container.Options, _ *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) configContent := `[crio] [crio.runtime] @@ -121,14 +121,14 @@ monitor_path = "/usr/libexec/crio/conmon" [crio.image] signature_policy = "/etc/crio/policy.json" ` - err := os.WriteFile(co.Config, []byte(configContent), 0600) + err := os.WriteFile(co.TopLevelConfigPath, []byte(configContent), 0600) require.NoError(t, err) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, _ *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actualTopLevel, err := os.ReadFile(co.Config) + actualTopLevel, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expectedTopLevel := `[crio] @@ -180,11 +180,11 @@ signature_policy = "/etc/crio/policy.json" return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) require.NoFileExists(t, co.DropInConfig) - actualTopLevel, err := os.ReadFile(co.Config) + actualTopLevel, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // Leaves original config unchanged @@ -209,18 +209,18 @@ signature_policy = "/etc/crio/policy.json" { description: "config mode: existing config with nvidia runtime already present", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/crio/crio.conf", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: true, - RestartMode: "none", + TopLevelConfigPath: "{{ .testRoot }}/etc/crio/crio.conf", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: true, + RestartMode: "none", }, options: Options{ configMode: "config", }, prepareEnvironment: func(t *testing.T, co *container.Options, _ *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) configContent := `[crio] [crio.runtime] @@ -234,14 +234,14 @@ runtime_type = "oci" runtime_path = "/old/path/nvidia-container-runtime" runtime_type = "oci" ` - err := os.WriteFile(co.Config, []byte(configContent), 0600) + err := os.WriteFile(co.TopLevelConfigPath, []byte(configContent), 0600) require.NoError(t, err) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, _ *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actualTopLevel, err := os.ReadFile(co.Config) + actualTopLevel, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // TODO: Do we expect the top-level config to change? i.e. Should @@ -290,9 +290,9 @@ runtime_type = "oci" return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actualTopLevel, err := os.ReadFile(co.Config) + actualTopLevel, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // TODO: Do we expect the top-level config to change? i.e. Should @@ -320,18 +320,18 @@ runtime_type = "oci" { description: "config mode: complex config with multiple settings", containerOptions: container.Options{ - Config: "{{ .testRoot }}/etc/crio/crio.conf", - DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", - RuntimeName: "nvidia", - RuntimeDir: "/usr/bin", - SetAsDefault: false, - RestartMode: "none", + TopLevelConfigPath: "{{ .testRoot }}/etc/crio/crio.conf", + DropInConfig: "{{ .testRoot }}/conf.d/99-nvidia.toml", + RuntimeName: "nvidia", + RuntimeDir: "/usr/bin", + SetAsDefault: false, + RestartMode: "none", }, options: Options{ configMode: "config", }, prepareEnvironment: func(t *testing.T, co *container.Options, _ *Options) error { - require.NoError(t, os.MkdirAll(filepath.Dir(co.Config), 0755)) + require.NoError(t, os.MkdirAll(filepath.Dir(co.TopLevelConfigPath), 0755)) configContent := `[crio] [crio.runtime] @@ -364,14 +364,14 @@ plugin_dirs = [ "/usr/libexec/cni" ] ` - err := os.WriteFile(co.Config, []byte(configContent), 0600) + err := os.WriteFile(co.TopLevelConfigPath, []byte(configContent), 0600) require.NoError(t, err) return nil }, assertSetupPostConditions: func(t *testing.T, co *container.Options, _ *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) expected := `[crio] @@ -441,9 +441,9 @@ plugin_dirs = [ return nil }, assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { - require.FileExists(t, co.Config) + require.FileExists(t, co.TopLevelConfigPath) - actual, err := os.ReadFile(co.Config) + actual, err := os.ReadFile(co.TopLevelConfigPath) require.NoError(t, err) // Should restore to original complex config @@ -628,7 +628,7 @@ plugin_dirs = [ t.Run(tc.description, func(t *testing.T) { // Update any paths as required testRoot := t.TempDir() - tc.containerOptions.Config = strings.ReplaceAll(tc.containerOptions.Config, "{{ .testRoot }}", testRoot) + tc.containerOptions.TopLevelConfigPath = strings.ReplaceAll(tc.containerOptions.TopLevelConfigPath, "{{ .testRoot }}", testRoot) tc.containerOptions.DropInConfig = strings.ReplaceAll(tc.containerOptions.DropInConfig, "{{ .testRoot }}", testRoot) tc.options.hooksDir = strings.ReplaceAll(tc.options.hooksDir, "{{ .testRoot }}", testRoot) tc.options.hookFilename = "99-nvidia.json" diff --git a/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go b/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go index f9e986937..4cb66dd9d 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go +++ b/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go @@ -201,11 +201,11 @@ func GetLowlevelRuntimePaths(o *container.Options) ([]string, error) { func getRuntimeConfig(o *container.Options) (engine.Interface, error) { return crio.New( - crio.WithTopLevelConfigPath(o.Config), + crio.WithTopLevelConfigPath(o.TopLevelConfigPath), crio.WithConfigSource( toml.LoadFirst( crio.CommandLineSource(o.HostRootMount, o.ExecutablePath), - toml.FromFile(o.Config), + toml.FromFile(o.TopLevelConfigPath), ), ), ) diff --git a/cmd/nvidia-ctk-installer/container/runtime/docker/docker.go b/cmd/nvidia-ctk-installer/container/runtime/docker/docker.go index e0987f933..0f61a2246 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/docker/docker.go +++ b/cmd/nvidia-ctk-installer/container/runtime/docker/docker.go @@ -96,7 +96,7 @@ func RestartDocker(o *container.Options) error { func GetLowlevelRuntimePaths(o *container.Options) ([]string, error) { cfg, err := docker.New( - docker.WithPath(o.Config), + docker.WithPath(o.TopLevelConfigPath), ) if err != nil { return nil, fmt.Errorf("unable to load docker config: %w", err) @@ -106,6 +106,6 @@ func GetLowlevelRuntimePaths(o *container.Options) ([]string, error) { func getRuntimeConfig(o *container.Options) (engine.Interface, error) { return docker.New( - docker.WithPath(o.Config), + docker.WithPath(o.TopLevelConfigPath), ) } diff --git a/cmd/nvidia-ctk-installer/container/runtime/runtime.go b/cmd/nvidia-ctk-installer/container/runtime/runtime.go index 22a307848..cfc006dc8 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/runtime.go +++ b/cmd/nvidia-ctk-installer/container/runtime/runtime.go @@ -51,7 +51,7 @@ func Flags(opts *Options) []cli.Flag { Name: "config", Usage: "Path to the runtime config file", Value: runtimeSpecificDefault, - Destination: &opts.Config, + Destination: &opts.TopLevelConfigPath, Sources: cli.EnvVars("RUNTIME_CONFIG", "CONTAINERD_CONFIG", "DOCKER_CONFIG"), }, &cli.StringFlag{ @@ -145,8 +145,8 @@ func (opts *Options) Validate(logger logger.Interface, c *cli.Command, runtime s // TODO: Add the runtime-specific DropInConfigs here. switch runtime { case containerd.Name: - if opts.Config == runtimeSpecificDefault { - opts.Config = containerd.DefaultConfig + if opts.TopLevelConfigPath == runtimeSpecificDefault { + opts.TopLevelConfigPath = containerd.DefaultConfig } if opts.DropInConfig == runtimeSpecificDefault { opts.DropInConfig = containerd.DefaultDropInConfig @@ -158,8 +158,8 @@ func (opts *Options) Validate(logger logger.Interface, c *cli.Command, runtime s opts.RestartMode = containerd.DefaultRestartMode } case crio.Name: - if opts.Config == runtimeSpecificDefault { - opts.Config = crio.DefaultConfig + if opts.TopLevelConfigPath == runtimeSpecificDefault { + opts.TopLevelConfigPath = crio.DefaultConfig } if opts.DropInConfig == runtimeSpecificDefault { opts.DropInConfig = crio.DefaultDropInConfig @@ -171,8 +171,8 @@ func (opts *Options) Validate(logger logger.Interface, c *cli.Command, runtime s opts.RestartMode = crio.DefaultRestartMode } case docker.Name: - if opts.Config == runtimeSpecificDefault { - opts.Config = docker.DefaultConfig + if opts.TopLevelConfigPath == runtimeSpecificDefault { + opts.TopLevelConfigPath = docker.DefaultConfig } // Docker does not support drop-in configs. if opts.DropInConfig == runtimeSpecificDefault {