mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-04-06 21:44:06 +00:00
Merge pull request #805 from alam0rt/add-v3-containerd-config
Add support for containerd v3 configs
This commit is contained in:
commit
11acbe7ca2
@ -18,12 +18,13 @@ package engine
|
|||||||
|
|
||||||
// Interface defines the API for a runtime config updater.
|
// Interface defines the API for a runtime config updater.
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
DefaultRuntime() string
|
|
||||||
AddRuntime(string, string, bool) error
|
AddRuntime(string, string, bool) error
|
||||||
Set(string, interface{})
|
DefaultRuntime() string
|
||||||
|
GetRuntimeConfig(string) (RuntimeConfig, error)
|
||||||
RemoveRuntime(string) error
|
RemoveRuntime(string) error
|
||||||
Save(string) (int64, error)
|
Save(string) (int64, error)
|
||||||
GetRuntimeConfig(string) (RuntimeConfig, error)
|
Set(string, interface{})
|
||||||
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeConfig defines the interface to query container runtime handler configuration
|
// RuntimeConfig defines the interface to query container runtime handler configuration
|
||||||
|
@ -30,40 +30,40 @@ func (c *Config) AddRuntime(name string, path string, setAsDefault bool) error {
|
|||||||
}
|
}
|
||||||
config := *c.Tree
|
config := *c.Tree
|
||||||
|
|
||||||
config.Set("version", int64(2))
|
config.Set("version", c.Version)
|
||||||
|
|
||||||
runtimeNamesForConfig := engine.GetLowLevelRuntimes(c)
|
runtimeNamesForConfig := engine.GetLowLevelRuntimes(c)
|
||||||
for _, r := range runtimeNamesForConfig {
|
for _, r := range runtimeNamesForConfig {
|
||||||
options := config.GetSubtreeByPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", r})
|
options := config.GetSubtreeByPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", r})
|
||||||
if options == nil {
|
if options == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.Logger.Debugf("using options from runtime %v: %v", r, options)
|
c.Logger.Debugf("using options from runtime %v: %v", r, options)
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name}, options.Copy())
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name}, options.Copy())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name}) == nil {
|
if config.GetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name}) == nil {
|
||||||
c.Logger.Warningf("could not infer options from runtimes %v; using defaults", runtimeNamesForConfig)
|
c.Logger.Warningf("could not infer options from runtimes %v; using defaults", runtimeNamesForConfig)
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "runtime_type"}, c.RuntimeType)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "runtime_type"}, c.RuntimeType)
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "runtime_root"}, "")
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "runtime_root"}, "")
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "runtime_engine"}, "")
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "runtime_engine"}, "")
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "privileged_without_host_devices"}, false)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "privileged_without_host_devices"}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.ContainerAnnotations) > 0 {
|
if len(c.ContainerAnnotations) > 0 {
|
||||||
annotations, err := c.getRuntimeAnnotations([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "container_annotations"})
|
annotations, err := c.getRuntimeAnnotations([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "container_annotations"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
annotations = append(c.ContainerAnnotations, annotations...)
|
annotations = append(c.ContainerAnnotations, annotations...)
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "container_annotations"}, annotations)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "container_annotations"}, annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name, "options", "BinaryName"}, path)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name, "options", "BinaryName"}, path)
|
||||||
|
|
||||||
if setAsDefault {
|
if setAsDefault {
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"}, name)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "default_runtime_name"}, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
*c.Tree = config
|
*c.Tree = config
|
||||||
@ -99,13 +99,13 @@ func (c *Config) getRuntimeAnnotations(path []string) ([]string, error) {
|
|||||||
// Set sets the specified containerd option.
|
// Set sets the specified containerd option.
|
||||||
func (c *Config) Set(key string, value interface{}) {
|
func (c *Config) Set(key string, value interface{}) {
|
||||||
config := *c.Tree
|
config := *c.Tree
|
||||||
config.SetPath([]string{"plugins", "io.containerd.grpc.v1.cri", key}, value)
|
config.SetPath([]string{"plugins", c.CRIRuntimePluginName, key}, value)
|
||||||
*c.Tree = config
|
*c.Tree = config
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultRuntime returns the default runtime for the cri-o config
|
// DefaultRuntime returns the default runtime for the cri-o config
|
||||||
func (c Config) DefaultRuntime() string {
|
func (c Config) DefaultRuntime() string {
|
||||||
if runtime, ok := c.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"}).(string); ok {
|
if runtime, ok := c.GetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "default_runtime_name"}).(string); ok {
|
||||||
return runtime
|
return runtime
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
@ -119,14 +119,14 @@ func (c *Config) RemoveRuntime(name string) error {
|
|||||||
|
|
||||||
config := *c.Tree
|
config := *c.Tree
|
||||||
|
|
||||||
config.DeletePath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name})
|
config.DeletePath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name})
|
||||||
if runtime, ok := config.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"}).(string); ok {
|
if runtime, ok := config.GetPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "default_runtime_name"}).(string); ok {
|
||||||
if runtime == name {
|
if runtime == name {
|
||||||
config.DeletePath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"})
|
config.DeletePath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "default_runtime_name"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimePath := []string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name}
|
runtimePath := []string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name}
|
||||||
for i := 0; i < len(runtimePath); i++ {
|
for i := 0; i < len(runtimePath); i++ {
|
||||||
if runtimes, ok := config.GetPath(runtimePath[:len(runtimePath)-i]).(*toml.Tree); ok {
|
if runtimes, ok := config.GetPath(runtimePath[:len(runtimePath)-i]).(*toml.Tree); ok {
|
||||||
if len(runtimes.Keys()) == 0 {
|
if len(runtimes.Keys()) == 0 {
|
@ -46,7 +46,7 @@ func TestAddRuntime(t *testing.T) {
|
|||||||
privileged_without_host_devices = false
|
privileged_without_host_devices = false
|
||||||
runtime_engine = ""
|
runtime_engine = ""
|
||||||
runtime_root = ""
|
runtime_root = ""
|
||||||
runtime_type = ""
|
runtime_type = "io.containerd.runc.v2"
|
||||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test.options]
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test.options]
|
||||||
BinaryName = "/usr/bin/test"
|
BinaryName = "/usr/bin/test"
|
||||||
`,
|
`,
|
||||||
@ -195,24 +195,85 @@ func TestAddRuntime(t *testing.T) {
|
|||||||
SystemdCgroup = false
|
SystemdCgroup = false
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "empty v3 spec is supported",
|
||||||
|
config: `
|
||||||
|
version = 3
|
||||||
|
`,
|
||||||
|
expectedConfig: `
|
||||||
|
version = 3
|
||||||
|
[plugins]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime"]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.test]
|
||||||
|
privileged_without_host_devices = false
|
||||||
|
runtime_engine = ""
|
||||||
|
runtime_root = ""
|
||||||
|
runtime_type = "io.containerd.runc.v2"
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.test.options]
|
||||||
|
BinaryName = "/usr/bin/test"
|
||||||
|
`,
|
||||||
|
expectedError: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "v3 spec is supported",
|
||||||
|
config: `
|
||||||
|
version = 3
|
||||||
|
[plugins]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime"]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc]
|
||||||
|
privileged_without_host_devices = true
|
||||||
|
runtime_engine = "engine"
|
||||||
|
runtime_root = "root"
|
||||||
|
runtime_type = "type"
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc.options]
|
||||||
|
BinaryName = "/usr/bin/runc"
|
||||||
|
SystemdCgroup = true
|
||||||
|
`,
|
||||||
|
expectedConfig: `
|
||||||
|
version = 3
|
||||||
|
[plugins]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime"]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes]
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc]
|
||||||
|
privileged_without_host_devices = true
|
||||||
|
runtime_engine = "engine"
|
||||||
|
runtime_root = "root"
|
||||||
|
runtime_type = "type"
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runc.options]
|
||||||
|
BinaryName = "/usr/bin/runc"
|
||||||
|
SystemdCgroup = true
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.test]
|
||||||
|
privileged_without_host_devices = true
|
||||||
|
runtime_engine = "engine"
|
||||||
|
runtime_root = "root"
|
||||||
|
runtime_type = "type"
|
||||||
|
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.test.options]
|
||||||
|
BinaryName = "/usr/bin/test"
|
||||||
|
SystemdCgroup = true
|
||||||
|
`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
cfg, err := toml.Load(tc.config)
|
|
||||||
require.NoError(t, err)
|
|
||||||
expectedConfig, err := toml.Load(tc.expectedConfig)
|
expectedConfig, err := toml.Load(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
c := &Config{
|
c, err := New(
|
||||||
Logger: logger,
|
WithLogger(logger),
|
||||||
Tree: cfg,
|
WithConfigSource(toml.FromString(tc.config)),
|
||||||
}
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = c.AddRuntime("test", "/usr/bin/test", tc.setAsDefault)
|
err = c.AddRuntime("test", "/usr/bin/test", tc.setAsDefault)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.EqualValues(t, expectedConfig.String(), cfg.String())
|
require.EqualValues(t, expectedConfig.String(), c.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,13 +360,13 @@ func TestGetRuntimeConfig(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
cfg, err := toml.Load(config)
|
|
||||||
|
c, err := New(
|
||||||
|
WithLogger(logger),
|
||||||
|
WithConfigSource(toml.FromString(config)),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
c := &Config{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
}
|
|
||||||
rc, err := c.GetRuntimeConfig(tc.runtime)
|
rc, err := c.GetRuntimeConfig(tc.runtime)
|
||||||
require.Equal(t, tc.expectedError, err)
|
require.Equal(t, tc.expectedError, err)
|
||||||
require.Equal(t, tc.expected, rc.GetBinaryPath())
|
require.Equal(t, tc.expected, rc.GetBinaryPath())
|
@ -70,18 +70,20 @@ func (c *ConfigV1) AddRuntime(name string, path string, setAsDefault bool) error
|
|||||||
config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "BinaryName"}, path)
|
config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "BinaryName"}, path)
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "Runtime"}, path)
|
config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "Runtime"}, path)
|
||||||
|
|
||||||
if setAsDefault && c.UseDefaultRuntimeName {
|
if setAsDefault {
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"}, name)
|
if !c.UseLegacyConfig {
|
||||||
} else if setAsDefault {
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"}, name)
|
||||||
// Note: This is deprecated in containerd 1.4.0 and will be removed in 1.5.0
|
} else {
|
||||||
if config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime"}) == nil {
|
// Note: This is deprecated in containerd 1.4.0 and will be removed in 1.5.0
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_type"}, c.RuntimeType)
|
if config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime"}) == nil {
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_root"}, "")
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_type"}, c.RuntimeType)
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_engine"}, "")
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_root"}, "")
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "privileged_without_host_devices"}, false)
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_engine"}, "")
|
||||||
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "privileged_without_host_devices"}, false)
|
||||||
|
}
|
||||||
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "BinaryName"}, path)
|
||||||
|
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "Runtime"}, path)
|
||||||
}
|
}
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "BinaryName"}, path)
|
|
||||||
config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "Runtime"}, path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*c.Tree = config
|
*c.Tree = config
|
||||||
|
@ -200,20 +200,21 @@ func TestAddRuntimeV1(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
cfg, err := toml.Load(tc.config)
|
|
||||||
require.NoError(t, err)
|
|
||||||
expectedConfig, err := toml.Load(tc.expectedConfig)
|
expectedConfig, err := toml.Load(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
c := &ConfigV1{
|
c, err := New(
|
||||||
Logger: logger,
|
WithLogger(logger),
|
||||||
Tree: cfg,
|
WithConfigSource(toml.FromString(tc.config)),
|
||||||
}
|
WithUseLegacyConfig(true),
|
||||||
|
WithRuntimeType(""),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = c.AddRuntime("test", "/usr/bin/test", tc.setAsDefault)
|
err = c.AddRuntime("test", "/usr/bin/test", tc.setAsDefault)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.EqualValues(t, expectedConfig.String(), cfg.String())
|
require.EqualValues(t, expectedConfig.String(), c.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,28 @@ import (
|
|||||||
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
|
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultConfigVersion = 2
|
||||||
|
defaultRuntimeType = "io.containerd.runc.v2"
|
||||||
|
)
|
||||||
|
|
||||||
// Config represents the containerd config
|
// Config represents the containerd config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
*toml.Tree
|
*toml.Tree
|
||||||
Logger logger.Interface
|
Version int64
|
||||||
RuntimeType string
|
Logger logger.Interface
|
||||||
UseDefaultRuntimeName bool
|
RuntimeType string
|
||||||
ContainerAnnotations []string
|
ContainerAnnotations []string
|
||||||
|
// UseLegacyConfig indicates whether a config file pre v1.3 should be generated.
|
||||||
|
// For version 1 config prior to containerd v1.4 the default runtime was
|
||||||
|
// specified in a containerd.runtimes.default_runtime section.
|
||||||
|
// This was deprecated in v1.4 in favour of containerd.default_runtime_name.
|
||||||
|
// Support for this section has been removed in v2.0.
|
||||||
|
UseLegacyConfig bool
|
||||||
|
// CRIRuntimePluginName represents the fully qualified name of the containerd plugin
|
||||||
|
// for the CRI runtime service. The name of this plugin was changed in v3 of the
|
||||||
|
// containerd configuration file.
|
||||||
|
CRIRuntimePluginName string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ engine.Interface = (*Config)(nil)
|
var _ engine.Interface = (*Config)(nil)
|
||||||
@ -55,7 +70,8 @@ func (c *containerdCfgRuntime) GetBinaryPath() string {
|
|||||||
// New creates a containerd config with the specified options
|
// New creates a containerd config with the specified options
|
||||||
func New(opts ...Option) (engine.Interface, error) {
|
func New(opts ...Option) (engine.Interface, error) {
|
||||||
b := &builder{
|
b := &builder{
|
||||||
runtimeType: defaultRuntimeType,
|
configVersion: defaultConfigVersion,
|
||||||
|
runtimeType: defaultRuntimeType,
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(b)
|
opt(b)
|
||||||
@ -72,55 +88,74 @@ func New(opts ...Option) (engine.Interface, error) {
|
|||||||
return nil, fmt.Errorf("failed to load config: %v", err)
|
return nil, fmt.Errorf("failed to load config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configVersion, err := b.parseVersion(tomlConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse config version: %w", err)
|
||||||
|
}
|
||||||
|
b.logger.Infof("Using config version %v", configVersion)
|
||||||
|
|
||||||
|
criRuntimePluginName, err := b.criRuntimePluginName(configVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get CRI runtime plugin name: %w", err)
|
||||||
|
}
|
||||||
|
b.logger.Infof("Using CRI runtime plugin name %q", criRuntimePluginName)
|
||||||
|
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
Tree: tomlConfig,
|
Tree: tomlConfig,
|
||||||
Logger: b.logger,
|
Version: configVersion,
|
||||||
RuntimeType: b.runtimeType,
|
CRIRuntimePluginName: criRuntimePluginName,
|
||||||
UseDefaultRuntimeName: b.useLegacyConfig,
|
Logger: b.logger,
|
||||||
ContainerAnnotations: b.containerAnnotations,
|
RuntimeType: b.runtimeType,
|
||||||
|
UseLegacyConfig: b.useLegacyConfig,
|
||||||
|
ContainerAnnotations: b.containerAnnotations,
|
||||||
}
|
}
|
||||||
|
|
||||||
version, err := cfg.parseVersion(b.useLegacyConfig)
|
switch configVersion {
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse config version: %v", err)
|
|
||||||
}
|
|
||||||
switch version {
|
|
||||||
case 1:
|
case 1:
|
||||||
return (*ConfigV1)(cfg), nil
|
return (*ConfigV1)(cfg), nil
|
||||||
case 2:
|
default:
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("unsupported config version: %v", version)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseVersion returns the version of the config
|
// parseVersion returns the version of the config
|
||||||
func (c *Config) parseVersion(useLegacyConfig bool) (int, error) {
|
func (b *builder) parseVersion(c *toml.Tree) (int64, error) {
|
||||||
defaultVersion := 2
|
if c == nil || len(c.Keys()) == 0 {
|
||||||
if useLegacyConfig {
|
// No config exists, or the config file is empty.
|
||||||
defaultVersion = 1
|
if b.useLegacyConfig {
|
||||||
|
// If a legacy config is explicitly requested, we default to a v1 config.
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
// Use the requested version.
|
||||||
|
return int64(b.configVersion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := c.Get("version").(type) {
|
switch v := c.Get("version").(type) {
|
||||||
case nil:
|
case nil:
|
||||||
switch len(c.Keys()) {
|
return 1, nil
|
||||||
case 0: // No config exists, or the config file is empty, use version inferred from containerd
|
|
||||||
return defaultVersion, nil
|
|
||||||
default: // A config file exists, has content, and no version is set
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
case int64:
|
case int64:
|
||||||
return int(v), nil
|
return v, nil
|
||||||
default:
|
default:
|
||||||
return -1, fmt.Errorf("unsupported type for version field: %v", v)
|
return -1, fmt.Errorf("unsupported type for version field: %v", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *builder) criRuntimePluginName(configVersion int64) (string, error) {
|
||||||
|
switch configVersion {
|
||||||
|
case 1:
|
||||||
|
return "cri", nil
|
||||||
|
case 2:
|
||||||
|
return "io.containerd.grpc.v1.cri", nil
|
||||||
|
default:
|
||||||
|
return "io.containerd.cri.v1.runtime", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
|
func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
|
||||||
if c == nil || c.Tree == nil {
|
if c == nil || c.Tree == nil {
|
||||||
return nil, fmt.Errorf("config is nil")
|
return nil, fmt.Errorf("config is nil")
|
||||||
}
|
}
|
||||||
runtimeData := c.GetSubtreeByPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name})
|
runtimeData := c.GetSubtreeByPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name})
|
||||||
return &containerdCfgRuntime{
|
return &containerdCfgRuntime{
|
||||||
tree: runtimeData,
|
tree: runtimeData,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -21,16 +21,13 @@ import (
|
|||||||
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
|
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultRuntimeType = "io.containerd.runc.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type builder struct {
|
type builder struct {
|
||||||
logger logger.Interface
|
logger logger.Interface
|
||||||
configSource toml.Loader
|
configSource toml.Loader
|
||||||
|
configVersion int
|
||||||
|
useLegacyConfig bool
|
||||||
path string
|
path string
|
||||||
runtimeType string
|
runtimeType string
|
||||||
useLegacyConfig bool
|
|
||||||
containerAnnotations []string
|
containerAnnotations []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,13 +62,20 @@ func WithRuntimeType(runtimeType string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithUseLegacyConfig sets the useLegacyConfig flag for the config builder
|
// WithUseLegacyConfig sets the useLegacyConfig flag for the config builder.
|
||||||
func WithUseLegacyConfig(useLegacyConfig bool) Option {
|
func WithUseLegacyConfig(useLegacyConfig bool) Option {
|
||||||
return func(b *builder) {
|
return func(b *builder) {
|
||||||
b.useLegacyConfig = useLegacyConfig
|
b.useLegacyConfig = useLegacyConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithConfigVersion sets the config version for the config builder
|
||||||
|
func WithConfigVersion(configVersion int) Option {
|
||||||
|
return func(b *builder) {
|
||||||
|
b.configVersion = configVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithContainerAnnotations sets the container annotations for the config builder
|
// WithContainerAnnotations sets the container annotations for the config builder
|
||||||
func WithContainerAnnotations(containerAnnotations ...string) Option {
|
func WithContainerAnnotations(containerAnnotations ...string) Option {
|
||||||
return func(b *builder) {
|
return func(b *builder) {
|
||||||
|
@ -166,3 +166,13 @@ func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
|
|||||||
}
|
}
|
||||||
return &dockerRuntime{}, nil
|
return &dockerRuntime{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the JSON config.
|
||||||
|
func (c Config) String() string {
|
||||||
|
output, err := json.MarshalIndent(c, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("invalid JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(output)
|
||||||
|
}
|
||||||
|
26
pkg/config/toml/source-map.go
Normal file
26
pkg/config/toml/source-map.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
# Copyright 2024 NVIDIA CORPORATION
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
package toml
|
||||||
|
|
||||||
|
type tomlMap map[string]interface{}
|
||||||
|
|
||||||
|
var _ Loader = (*tomlFile)(nil)
|
||||||
|
|
||||||
|
// Load loads the contents of the specified TOML file as a map.
|
||||||
|
func (l tomlMap) Load() (*Tree, error) {
|
||||||
|
return LoadMap(l)
|
||||||
|
}
|
26
pkg/config/toml/source-string.go
Normal file
26
pkg/config/toml/source-string.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
# Copyright 2024 NVIDIA CORPORATION
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
package toml
|
||||||
|
|
||||||
|
type tomlString string
|
||||||
|
|
||||||
|
var _ Loader = (*tomlFile)(nil)
|
||||||
|
|
||||||
|
// Load loads the contents of the specified TOML file as a map.
|
||||||
|
func (l tomlString) Load() (*Tree, error) {
|
||||||
|
return Load(string(l))
|
||||||
|
}
|
@ -25,15 +25,6 @@ type Loader interface {
|
|||||||
Load() (*Tree, error)
|
Load() (*Tree, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromFile creates a TOML source from the specified file.
|
|
||||||
// If an empty string is passed an empty toml config is used.
|
|
||||||
func FromFile(path string) Loader {
|
|
||||||
if path == "" {
|
|
||||||
return Empty
|
|
||||||
}
|
|
||||||
return tomlFile(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromCommandLine creates a TOML source from the output of a shell command and its corresponding args.
|
// FromCommandLine creates a TOML source from the output of a shell command and its corresponding args.
|
||||||
// If the command is empty, an empty config is returned.
|
// If the command is empty, an empty config is returned.
|
||||||
func FromCommandLine(cmds ...string) Loader {
|
func FromCommandLine(cmds ...string) Loader {
|
||||||
@ -45,3 +36,30 @@ func FromCommandLine(cmds ...string) Loader {
|
|||||||
args: cmds[1:],
|
args: cmds[1:],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromFile creates a TOML source from the specified file.
|
||||||
|
// If an empty string is passed an empty toml config is used.
|
||||||
|
func FromFile(path string) Loader {
|
||||||
|
if path == "" {
|
||||||
|
return Empty
|
||||||
|
}
|
||||||
|
return tomlFile(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromMap creates a TOML source for the specified map.
|
||||||
|
// If an empty map is passed and empty tomly config is used.
|
||||||
|
func FromMap(m map[string]interface{}) Loader {
|
||||||
|
if m == nil {
|
||||||
|
return Empty
|
||||||
|
}
|
||||||
|
return tomlMap(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromString creates a TOML source for the specified contents.
|
||||||
|
// If an empty string is passed an empty toml config is used.
|
||||||
|
func FromString(contents string) Loader {
|
||||||
|
if contents == "" {
|
||||||
|
return Empty
|
||||||
|
}
|
||||||
|
return tomlString(contents)
|
||||||
|
}
|
||||||
|
@ -88,37 +88,36 @@ func TestUpdateV1ConfigDefaultRuntime(t *testing.T) {
|
|||||||
SetAsDefault: tc.setAsDefault,
|
SetAsDefault: tc.setAsDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.Empty.Load()
|
v1, err := containerd.New(
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.Empty),
|
||||||
v1 := &containerd.ConfigV1{
|
containerd.WithRuntimeType(runtimeType),
|
||||||
Logger: logger,
|
containerd.WithUseLegacyConfig(tc.legacyConfig),
|
||||||
Tree: cfg,
|
containerd.WithConfigVersion(1),
|
||||||
UseDefaultRuntimeName: !tc.legacyConfig,
|
)
|
||||||
RuntimeType: runtimeType,
|
require.NoError(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v1)
|
err = o.UpdateConfig(v1)
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
require.NoError(t, err)
|
||||||
|
|
||||||
defaultRuntimeName := v1.GetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"})
|
cfg := v1.(*containerd.ConfigV1)
|
||||||
require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName, "%d: %v", i, tc)
|
defaultRuntimeName := cfg.GetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"})
|
||||||
|
require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName)
|
||||||
|
|
||||||
defaultRuntime := v1.GetPath([]string{"plugins", "cri", "containerd", "default_runtime"})
|
defaultRuntime := cfg.GetPath([]string{"plugins", "cri", "containerd", "default_runtime"})
|
||||||
if tc.expectedDefaultRuntimeBinary == nil {
|
if tc.expectedDefaultRuntimeBinary == nil {
|
||||||
require.Nil(t, defaultRuntime, "%d: %v", i, tc)
|
require.Nil(t, defaultRuntime)
|
||||||
} else {
|
} else {
|
||||||
require.NotNil(t, defaultRuntime)
|
require.NotNil(t, defaultRuntime)
|
||||||
|
|
||||||
expected, err := defaultRuntimeTomlConfigV1(tc.expectedDefaultRuntimeBinary.(string))
|
expected, err := defaultRuntimeTomlConfigV1(tc.expectedDefaultRuntimeBinary.(string))
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configContents, _ := toml.Marshal(defaultRuntime.(*toml.Tree))
|
configContents, _ := toml.Marshal(defaultRuntime.(*toml.Tree))
|
||||||
expectedContents, _ := toml.Marshal(expected)
|
expectedContents, _ := toml.Marshal(expected)
|
||||||
|
|
||||||
require.Equal(t, string(expectedContents), string(configContents), "%d: %v: %v", i, tc)
|
require.Equal(t, string(expectedContents), string(configContents), "%d: %v: %v", i, tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,24 +233,22 @@ func TestUpdateV1Config(t *testing.T) {
|
|||||||
RuntimeDir: runtimeDir,
|
RuntimeDir: runtimeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.Empty.Load()
|
v1, err := containerd.New(
|
||||||
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.Empty),
|
||||||
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithConfigVersion(1),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v1 := &containerd.ConfigV1{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
UseDefaultRuntimeName: true,
|
|
||||||
RuntimeType: runtimeType,
|
|
||||||
ContainerAnnotations: []string{"cdi.k8s.io/*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v1)
|
err = o.UpdateConfig(v1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, expected.String(), cfg.String())
|
require.Equal(t, expected.String(), v1.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,29 +390,28 @@ func TestUpdateV1ConfigWithRuncPresent(t *testing.T) {
|
|||||||
RuntimeDir: runtimeDir,
|
RuntimeDir: runtimeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.TreeFromMap(runcConfigMapV1("/runc-binary"))
|
v1, err := containerd.New(
|
||||||
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.FromMap(runcConfigMapV1("/runc-binary"))),
|
||||||
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithConfigVersion(1),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v1 := &containerd.ConfigV1{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
UseDefaultRuntimeName: true,
|
|
||||||
RuntimeType: runtimeType,
|
|
||||||
ContainerAnnotations: []string{"cdi.k8s.io/*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v1)
|
err = o.UpdateConfig(v1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, expected.String(), cfg.String())
|
require.Equal(t, expected.String(), v1.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRevertV1Config(t *testing.T) {
|
func TestRevertV1Config(t *testing.T) {
|
||||||
|
logger, _ := testlog.NewNullLogger()
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
config map[string]interface {
|
config map[string]interface {
|
||||||
}
|
}
|
||||||
@ -469,25 +465,22 @@ func TestRevertV1Config(t *testing.T) {
|
|||||||
RuntimeName: "nvidia",
|
RuntimeName: "nvidia",
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.LoadMap(tc.config)
|
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expected)
|
expected, err := toml.TreeFromMap(tc.expected)
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v1 := &containerd.ConfigV1{
|
v1, err := containerd.New(
|
||||||
Tree: cfg,
|
containerd.WithLogger(logger),
|
||||||
UseDefaultRuntimeName: true,
|
containerd.WithConfigSource(toml.FromMap(tc.config)),
|
||||||
RuntimeType: runtimeType,
|
containerd.WithRuntimeType(runtimeType),
|
||||||
}
|
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = o.RevertConfig(v1)
|
err = o.RevertConfig(v1)
|
||||||
require.NoError(t, err, "%d: %v", i, tc)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configContents, _ := toml.Marshal(cfg)
|
require.Equal(t, expected.String(), v1.String())
|
||||||
expectedContents, _ := toml.Marshal(expected)
|
|
||||||
|
|
||||||
require.Equal(t, string(expectedContents), string(configContents), "%d: %v", i, tc)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,18 +72,19 @@ func TestUpdateV2ConfigDefaultRuntime(t *testing.T) {
|
|||||||
SetAsDefault: tc.setAsDefault,
|
SetAsDefault: tc.setAsDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.LoadMap(map[string]interface{}{})
|
v2, err := containerd.New(
|
||||||
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.Empty),
|
||||||
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v2 := &containerd.Config{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
RuntimeType: runtimeType,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v2)
|
err = o.UpdateConfig(v2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cfg := v2.(*containerd.Config)
|
||||||
|
|
||||||
defaultRuntimeName := cfg.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"})
|
defaultRuntimeName := cfg.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"})
|
||||||
require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName)
|
require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName)
|
||||||
})
|
})
|
||||||
@ -195,23 +196,21 @@ func TestUpdateV2Config(t *testing.T) {
|
|||||||
RuntimeDir: runtimeDir,
|
RuntimeDir: runtimeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.LoadMap(map[string]interface{}{})
|
v2, err := containerd.New(
|
||||||
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.Empty),
|
||||||
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v2 := &containerd.Config{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
RuntimeType: runtimeType,
|
|
||||||
ContainerAnnotations: []string{"cdi.k8s.io/*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v2)
|
err = o.UpdateConfig(v2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, expected.String(), cfg.String())
|
require.Equal(t, expected.String(), v2.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,28 +347,28 @@ func TestUpdateV2ConfigWithRuncPresent(t *testing.T) {
|
|||||||
RuntimeDir: runtimeDir,
|
RuntimeDir: runtimeDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.LoadMap(runcConfigMapV2("/runc-binary"))
|
v2, err := containerd.New(
|
||||||
|
containerd.WithLogger(logger),
|
||||||
|
containerd.WithConfigSource(toml.FromMap(runcConfigMapV2("/runc-binary"))),
|
||||||
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v2 := &containerd.Config{
|
|
||||||
Logger: logger,
|
|
||||||
Tree: cfg,
|
|
||||||
RuntimeType: runtimeType,
|
|
||||||
ContainerAnnotations: []string{"cdi.k8s.io/*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = o.UpdateConfig(v2)
|
err = o.UpdateConfig(v2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
expected, err := toml.TreeFromMap(tc.expectedConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, expected.String(), cfg.String())
|
require.Equal(t, expected.String(), v2.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRevertV2Config(t *testing.T) {
|
func TestRevertV2Config(t *testing.T) {
|
||||||
|
logger, _ := testlog.NewNullLogger()
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
config map[string]interface {
|
config map[string]interface {
|
||||||
}
|
}
|
||||||
@ -418,24 +417,21 @@ func TestRevertV2Config(t *testing.T) {
|
|||||||
RuntimeName: "nvidia",
|
RuntimeName: "nvidia",
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := toml.LoadMap(tc.config)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
expected, err := toml.TreeFromMap(tc.expected)
|
expected, err := toml.TreeFromMap(tc.expected)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v2 := &containerd.Config{
|
v2, err := containerd.New(
|
||||||
Tree: cfg,
|
containerd.WithLogger(logger),
|
||||||
RuntimeType: runtimeType,
|
containerd.WithConfigSource(toml.FromMap(tc.config)),
|
||||||
}
|
containerd.WithRuntimeType(runtimeType),
|
||||||
|
containerd.WithContainerAnnotations("cdi.k8s.io/*"),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = o.RevertConfig(v2)
|
err = o.RevertConfig(v2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
configContents, _ := toml.Marshal(cfg)
|
require.Equal(t, expected.String(), v2.String())
|
||||||
expectedContents, _ := toml.Marshal(expected)
|
|
||||||
|
|
||||||
require.Equal(t, string(expectedContents), string(configContents))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,6 +450,7 @@ func runtimeMapV2(binary string) map[string]interface{} {
|
|||||||
|
|
||||||
func runcConfigMapV2(binary string) map[string]interface{} {
|
func runcConfigMapV2(binary string) map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
|
"version": 2,
|
||||||
"plugins": map[string]interface{}{
|
"plugins": map[string]interface{}{
|
||||||
"io.containerd.grpc.v1.cri": map[string]interface{}{
|
"io.containerd.grpc.v1.cri": map[string]interface{}{
|
||||||
"containerd": map[string]interface{}{
|
"containerd": map[string]interface{}{
|
||||||
|
@ -52,8 +52,11 @@ type Options struct {
|
|||||||
func Flags(opts *Options) []cli.Flag {
|
func Flags(opts *Options) []cli.Flag {
|
||||||
flags := []cli.Flag{
|
flags := []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "use-legacy-config",
|
Name: "use-legacy-config",
|
||||||
Usage: "Specify whether a legacy (pre v1.3) config should be used",
|
Usage: "Specify whether a legacy (pre v1.3) config should be used. " +
|
||||||
|
"This ensures that a version 1 container config is created by default and that the " +
|
||||||
|
"containerd.runtimes.default_runtime config section is used to define the default " +
|
||||||
|
"runtime instead of container.default_runtime_name.",
|
||||||
Destination: &opts.useLegacyConfig,
|
Destination: &opts.useLegacyConfig,
|
||||||
EnvVars: []string{"CONTAINERD_USE_LEGACY_CONFIG"},
|
EnvVars: []string{"CONTAINERD_USE_LEGACY_CONFIG"},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user