Skip to content

Commit

Permalink
Add support for containerd version 3 config
Browse files Browse the repository at this point in the history
This change adds support for containerd configs with version=3.
From the perspective of the runtime configuration the contents of the
config are the same. This means that we just have to load the new
version and ensure that this is propagated to the generated config.

Note that we still use a default config of version=2 since we need to
ensure compatibility with older containerd versions (1.6.x and 1.7.x).

Signed-off-by: Sam Lockart <[email protected]>
Signed-off-by: Evan Lezar <[email protected]>
  • Loading branch information
alam0rt authored and elezar committed Nov 29, 2024
1 parent 1417c51 commit c11d433
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (c *Config) AddRuntime(name string, path string, setAsDefault bool) error {
}
config := *c.Tree

config.Set("version", int64(2))
config.Set("version", c.Version)

runtimeNamesForConfig := engine.GetLowLevelRuntimes(c)
for _, r := range runtimeNamesForConfig {
Expand Down
62 changes: 62 additions & 0 deletions pkg/config/engine/containerd/config_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,68 @@ func TestAddRuntime(t *testing.T) {
SystemdCgroup = false
`,
},
{
description: "empty v3 spec is supported",
config: `
version = 3
`,
expectedConfig: `
version = 3
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test]
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test.options]
BinaryName = "/usr/bin/test"
`,
expectedError: nil,
},
{
description: "v3 spec is supported",
config: `
version = 3
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
privileged_without_host_devices = true
runtime_engine = "engine"
runtime_root = "root"
runtime_type = "type"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = "/usr/bin/runc"
SystemdCgroup = true
`,
expectedConfig: `
version = 3
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
privileged_without_host_devices = true
runtime_engine = "engine"
runtime_root = "root"
runtime_type = "type"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = "/usr/bin/runc"
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test]
privileged_without_host_devices = true
runtime_engine = "engine"
runtime_root = "root"
runtime_type = "type"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.test.options]
BinaryName = "/usr/bin/test"
SystemdCgroup = true
`,
},
}

for _, tc := range testCases {
Expand Down
39 changes: 21 additions & 18 deletions pkg/config/engine/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
)

const (
defaultConfigVersion = 2
defaultRuntimeType = "io.containerd.runc.v2"
)

// Config represents the containerd config
type Config struct {
*toml.Tree
Version int64
Logger logger.Interface
RuntimeType string
UseDefaultRuntimeName bool
Expand Down Expand Up @@ -55,7 +61,8 @@ func (c *containerdCfgRuntime) GetBinaryPath() string {
// New creates a containerd config with the specified options
func New(opts ...Option) (engine.Interface, error) {
b := &builder{
runtimeType: defaultRuntimeType,
configVersion: defaultConfigVersion,
runtimeType: defaultRuntimeType,
}
for _, opt := range opts {
opt(b)
Expand All @@ -72,45 +79,41 @@ func New(opts ...Option) (engine.Interface, error) {
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)
}

cfg := &Config{
Tree: tomlConfig,
Version: configVersion,
Logger: b.logger,
RuntimeType: b.runtimeType,
UseDefaultRuntimeName: b.useLegacyConfig,
UseDefaultRuntimeName: configVersion == 1,
ContainerAnnotations: b.containerAnnotations,
}

version, err := cfg.parseVersion(b.useLegacyConfig)
if err != nil {
return nil, fmt.Errorf("failed to parse config version: %v", err)
}
switch version {
switch configVersion {
case 1:
return (*ConfigV1)(cfg), nil
case 2:
case 2, 3:
return cfg, nil
}

return nil, fmt.Errorf("unsupported config version: %v", version)
return nil, fmt.Errorf("unsupported config version: %v", configVersion)
}

// parseVersion returns the version of the config
func (c *Config) parseVersion(useLegacyConfig bool) (int, error) {
defaultVersion := 2
if useLegacyConfig {
defaultVersion = 1
}

func (b *builder) parseVersion(c *toml.Tree) (int64, error) {
switch v := c.Get("version").(type) {
case nil:
switch len(c.Keys()) {
case 0: // No config exists, or the config file is empty, use version inferred from containerd
return defaultVersion, nil
return int64(b.configVersion), nil
default: // A config file exists, has content, and no version is set
return 1, nil
}
case int64:
return int(v), nil
return v, nil
default:
return -1, fmt.Errorf("unsupported type for version field: %v", v)
}
Expand Down
15 changes: 9 additions & 6 deletions pkg/config/engine/containerd/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,12 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
)

const (
defaultRuntimeType = "io.containerd.runc.v2"
)

type builder struct {
logger logger.Interface
configSource toml.Loader
configVersion int
path string
runtimeType string
useLegacyConfig bool
containerAnnotations []string
}

Expand Down Expand Up @@ -68,7 +64,14 @@ func WithRuntimeType(runtimeType string) Option {
// WithUseLegacyConfig sets the useLegacyConfig flag for the config builder
func WithUseLegacyConfig(useLegacyConfig bool) Option {
return func(b *builder) {
b.useLegacyConfig = useLegacyConfig
b.configVersion = 1
}
}

// WithConfigVersion sets the config version for the config builder
func WithConfigVersion(configVersion int) Option {
return func(b *builder) {
b.configVersion = configVersion
}
}

Expand Down

0 comments on commit c11d433

Please sign in to comment.