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 72767f06b..c948b9acd 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go +++ b/cmd/nvidia-ctk-installer/container/runtime/containerd/config_test.go @@ -1777,6 +1777,113 @@ version = 3 require.NoFileExists(t, co.DropInConfig) + return nil + }, + }, + { + description: "setting drop-in-config to empty modifies existing config", + containerOptions: container.Options{ + TopLevelConfigPath: "{{ .testRoot }}/etc/containerd/config.toml", + DropInConfig: "", + 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.TopLevelConfigPath), 0755)) + + initialConfig := `version = 2 + +[plugins] + [plugins."io.containerd.grpc.v1.cri"] + [plugins."io.containerd.grpc.v1.cri".containerd] + default_runtime_name = "runc" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] + BinaryName = "/usr/bin/runc" +` + 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.TopLevelConfigPath) + + actual, err := os.ReadFile(co.TopLevelConfigPath) + require.NoError(t, err) + + expected := `version = 2 + +[plugins] + + [plugins."io.containerd.grpc.v1.cri"] + + [plugins."io.containerd.grpc.v1.cri".containerd] + default_runtime_name = "runc" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options] + BinaryName = "/usr/bin/nvidia-container-runtime" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia-cdi] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia-cdi.options] + BinaryName = "/usr/bin/nvidia-container-runtime.cdi" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia-legacy] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia-legacy.options] + BinaryName = "/usr/bin/nvidia-container-runtime.legacy" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] + BinaryName = "/usr/bin/runc" +` + require.Equal(t, expected, string(actual)) + + return nil + }, + assertCleanupPostConditions: func(t *testing.T, co *container.Options, o *Options) error { + require.FileExists(t, co.TopLevelConfigPath) + + actual, err := os.ReadFile(co.TopLevelConfigPath) + require.NoError(t, err) + + expected := `version = 2 + +[plugins] + + [plugins."io.containerd.grpc.v1.cri"] + + [plugins."io.containerd.grpc.v1.cri".containerd] + default_runtime_name = "runc" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] + runtime_type = "io.containerd.runc.v2" + + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] + BinaryName = "/usr/bin/runc" +` + require.Equal(t, expected, string(actual)) + return nil }, }, diff --git a/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go b/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go index a240979d8..a277cab82 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go +++ b/cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go @@ -183,6 +183,7 @@ func getRuntimeConfig(o *container.Options, co *Options) (engine.Interface, erro containerd.WithRuntimeType(co.runtimeType), containerd.WithUseLegacyConfig(co.useLegacyConfig), containerd.WithContainerAnnotations(co.containerAnnotationsFromCDIPrefixes()...), + containerd.WithDisableDropInConfig(o.DropInConfig == ""), } if o.DropInConfigHostPath != "" && o.DropInConfig != "" { options = append(options, diff --git a/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go b/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go index 07750e479..a4716dbea 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go +++ b/cmd/nvidia-ctk-installer/container/runtime/crio/crio.go @@ -222,5 +222,6 @@ func getRuntimeConfig(o *container.Options) (engine.Interface, error) { toml.FromFile(o.TopLevelConfigPath), ), ), + crio.WithDisableDropInConfig(o.DropInConfig == ""), ) } diff --git a/cmd/nvidia-ctk-installer/container/runtime/runtime.go b/cmd/nvidia-ctk-installer/container/runtime/runtime.go index 2894a3f75..c26b03277 100644 --- a/cmd/nvidia-ctk-installer/container/runtime/runtime.go +++ b/cmd/nvidia-ctk-installer/container/runtime/runtime.go @@ -56,7 +56,7 @@ func Flags(opts *Options) []cli.Flag { }, &cli.StringFlag{ Name: "drop-in-config", - Usage: "Path to the NVIDIA-specific drop-in config file", + Usage: "Path to the NVIDIA-specific drop-in config file. If this is empty, the top-level config is modified directly.", Value: runtimeSpecificDefault, Destination: &opts.DropInConfig, Sources: cli.EnvVars("RUNTIME_DROP_IN_CONFIG"), diff --git a/cmd/nvidia-ctk/runtime/configure/configure.go b/cmd/nvidia-ctk/runtime/configure/configure.go index 7fadee66c..44e85d657 100644 --- a/cmd/nvidia-ctk/runtime/configure/configure.go +++ b/cmd/nvidia-ctk/runtime/configure/configure.go @@ -302,12 +302,14 @@ func (m command) configureConfigFile(config *config) error { containerd.WithLogger(m.logger), containerd.WithTopLevelConfigPath(config.configFilePath), containerd.WithConfigSource(configSource), + containerd.WithDisableDropInConfig(config.dropInConfigPath == ""), ) case "crio": cfg, err = crio.New( crio.WithLogger(m.logger), crio.WithTopLevelConfigPath(config.configFilePath), crio.WithConfigSource(configSource), + crio.WithDisableDropInConfig(config.dropInConfigPath == ""), ) case "docker": cfg, err = docker.New( diff --git a/pkg/config/engine/containerd/containerd.go b/pkg/config/engine/containerd/containerd.go index 1576d2069..7b69cd83b 100644 --- a/pkg/config/engine/containerd/containerd.go +++ b/pkg/config/engine/containerd/containerd.go @@ -50,6 +50,7 @@ type configOptions struct { // for the CRI runtime service. The name of this plugin was changed in v3 of the // containerd configuration file. CRIRuntimePluginName string + DisableDropInConfig bool } var _ engine.Interface = (*Config)(nil) @@ -122,6 +123,10 @@ func New(opts ...Option) (engine.Interface, error) { // We return the sourceConfig as is. return (*ConfigV1)(sourceConfig), nil default: + if b.disableDropInConfig { + b.logger.Info("Drop-in config files are disabled. Modifying the source config directly.") + return sourceConfig, nil + } // For other versions, we create a DropInConfig with a reference to the // top-level config if present. topLevelConfig := &Config{ diff --git a/pkg/config/engine/containerd/option.go b/pkg/config/engine/containerd/option.go index 17f29b876..63218dacc 100644 --- a/pkg/config/engine/containerd/option.go +++ b/pkg/config/engine/containerd/option.go @@ -31,6 +31,8 @@ type builder struct { containerAnnotations []string containerToHostPathMap map[string]string + + disableDropInConfig bool } // Option defines a function that can be used to configure the config builder @@ -97,3 +99,10 @@ func WithContainerAnnotations(containerAnnotations ...string) Option { b.containerAnnotations = containerAnnotations } } + +// WithDisableDropInConfig disables the use of drop-in config files +func WithDisableDropInConfig(disable bool) Option { + return func(b *builder) { + b.disableDropInConfig = disable + } +} diff --git a/pkg/config/engine/crio/crio.go b/pkg/config/engine/crio/crio.go index 9effd7246..4b2df12bc 100644 --- a/pkg/config/engine/crio/crio.go +++ b/pkg/config/engine/crio/crio.go @@ -62,16 +62,22 @@ func New(opts ...Option) (engine.Interface, error) { b.configSource = toml.FromFile(b.topLevelConfigPath) } - sourceConfig, err := b.configSource.Load() + sourceConfigTree, err := b.configSource.Load() if err != nil { return nil, err } + sourceConfig := &Config{ + Tree: sourceConfigTree, + Logger: b.logger, + } + + if b.disableDropInConfig { + return sourceConfig, nil + } + cfg := &engine.Config{ - Source: &Config{ - Tree: sourceConfig, - Logger: b.logger, - }, + Source: sourceConfig, Destination: &Config{ Tree: toml.NewEmpty(), Logger: b.logger, diff --git a/pkg/config/engine/crio/option.go b/pkg/config/engine/crio/option.go index 4df7528f2..66b93531b 100644 --- a/pkg/config/engine/crio/option.go +++ b/pkg/config/engine/crio/option.go @@ -22,14 +22,22 @@ import ( ) type builder struct { - logger logger.Interface - configSource toml.Loader - topLevelConfigPath string + logger logger.Interface + configSource toml.Loader + topLevelConfigPath string + disableDropInConfig bool } // Option defines a function that can be used to configure the config builder type Option func(*builder) +// WithDisableDropInConfig disables the use of drop-in config files +func WithDisableDropInConfig(disable bool) Option { + return func(b *builder) { + b.disableDropInConfig = disable + } +} + // WithLogger sets the logger for the config builder func WithLogger(logger logger.Interface) Option { return func(b *builder) {