mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-02-04 03:56:23 +00:00
95bda3ad72
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 v3 config also requires a switch to the 'io.containerd.cri.v1.runtime' CRI runtime plugin. See: https://github.com/containerd/containerd/blob/v2.0.0/docs/PLUGINS.md https://github.com/containerd/containerd/issues/10132 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 <sam.lockart@zendesk.com> Signed-off-by: Evan Lezar <elezar@nvidia.com> Signed-off-by: Christopher Desiniotis <cdesiniotis@nvidia.com>
176 lines
5.0 KiB
Go
176 lines
5.0 KiB
Go
/**
|
|
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
|
#
|
|
# 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 containerd
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
|
|
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
|
|
"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
|
|
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)
|
|
|
|
type containerdCfgRuntime struct {
|
|
tree *toml.Tree
|
|
}
|
|
|
|
var _ engine.RuntimeConfig = (*containerdCfgRuntime)(nil)
|
|
|
|
// GetBinaryPath retrieves the path to the low-level runtime binary for a runtime.
|
|
// If no path is available, the empty string is returned.
|
|
func (c *containerdCfgRuntime) GetBinaryPath() string {
|
|
if c == nil || c.tree == nil {
|
|
return ""
|
|
}
|
|
|
|
binPath, _ := c.tree.GetPath([]string{"options", "BinaryName"}).(string)
|
|
return binPath
|
|
}
|
|
|
|
// New creates a containerd config with the specified options
|
|
func New(opts ...Option) (engine.Interface, error) {
|
|
b := &builder{
|
|
configVersion: defaultConfigVersion,
|
|
runtimeType: defaultRuntimeType,
|
|
}
|
|
for _, opt := range opts {
|
|
opt(b)
|
|
}
|
|
if b.logger == nil {
|
|
b.logger = logger.New()
|
|
}
|
|
if b.configSource == nil {
|
|
b.configSource = toml.FromFile(b.path)
|
|
}
|
|
|
|
tomlConfig, err := b.configSource.Load()
|
|
if err != nil {
|
|
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{
|
|
Tree: tomlConfig,
|
|
Version: configVersion,
|
|
CRIRuntimePluginName: criRuntimePluginName,
|
|
Logger: b.logger,
|
|
RuntimeType: b.runtimeType,
|
|
UseLegacyConfig: b.useLegacyConfig,
|
|
ContainerAnnotations: b.containerAnnotations,
|
|
}
|
|
|
|
switch configVersion {
|
|
case 1:
|
|
return (*ConfigV1)(cfg), nil
|
|
default:
|
|
return cfg, nil
|
|
}
|
|
}
|
|
|
|
// parseVersion returns the version of the config
|
|
func (b *builder) parseVersion(c *toml.Tree) (int64, error) {
|
|
if c == nil || len(c.Keys()) == 0 {
|
|
// No config exists, or the config file is empty.
|
|
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) {
|
|
case nil:
|
|
return 1, nil
|
|
case int64:
|
|
return v, nil
|
|
default:
|
|
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) {
|
|
if c == nil || c.Tree == nil {
|
|
return nil, fmt.Errorf("config is nil")
|
|
}
|
|
runtimeData := c.GetSubtreeByPath([]string{"plugins", c.CRIRuntimePluginName, "containerd", "runtimes", name})
|
|
return &containerdCfgRuntime{
|
|
tree: runtimeData,
|
|
}, nil
|
|
}
|
|
|
|
// CommandLineSource returns the CLI-based containerd config loader
|
|
func CommandLineSource(hostRoot string) toml.Loader {
|
|
return toml.FromCommandLine(chrootIfRequired(hostRoot, "containerd", "config", "dump")...)
|
|
}
|
|
|
|
func chrootIfRequired(hostRoot string, commandLine ...string) []string {
|
|
if hostRoot == "" || hostRoot == "/" {
|
|
return commandLine
|
|
}
|
|
|
|
return append([]string{"chroot", hostRoot}, commandLine...)
|
|
}
|