mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-03-28 11:23:40 +00:00
Rework default config generation to not use toml
Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
parent
bc6ca7ff88
commit
f78d3a858f
@ -26,7 +26,6 @@ import (
|
|||||||
|
|
||||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
|
||||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
|
||||||
"github.com/pelletier/go-toml"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -126,12 +125,10 @@ func (opts options) getFormattedConfig() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer := bytes.NewBuffer(nil)
|
buffer := bytes.NewBuffer(nil)
|
||||||
enc := toml.NewEncoder(buffer).Indentation("")
|
|
||||||
|
|
||||||
if err := enc.Encode(cfg); err != nil {
|
if _, err := cfg.Save(buffer); err != nil {
|
||||||
return nil, fmt.Errorf("invalid config: %v", err)
|
return nil, fmt.Errorf("unable to save config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fixComments(buffer.Bytes())
|
return fixComments(buffer.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,5 +18,7 @@ package config
|
|||||||
|
|
||||||
// ContainerCLIConfig stores the options for the nvidia-container-cli
|
// ContainerCLIConfig stores the options for the nvidia-container-cli
|
||||||
type ContainerCLIConfig struct {
|
type ContainerCLIConfig struct {
|
||||||
Root string `toml:"root"`
|
Root string `toml:"root"`
|
||||||
|
LoadKmods bool `toml:"load-kmods"`
|
||||||
|
Ldconfig string `toml:"ldconfig"`
|
||||||
}
|
}
|
||||||
|
@ -130,90 +130,37 @@ func getFromTree(toml *toml.Tree) (*Config, error) {
|
|||||||
|
|
||||||
// getDefault defines the default values for the config
|
// getDefault defines the default values for the config
|
||||||
func getDefault() (*Config, error) {
|
func getDefault() (*Config, error) {
|
||||||
tomlConfig, err := GetDefaultToml()
|
d := Config{
|
||||||
if err != nil {
|
AcceptEnvvarUnprivileged: true,
|
||||||
return nil, err
|
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
||||||
}
|
LoadKmods: true,
|
||||||
|
Ldconfig: getLdConfigPath(),
|
||||||
// tomlConfig above includes information about the default values and comments.
|
},
|
||||||
// we need to marshal it back to a string and then unmarshal it to strip the comments.
|
NVIDIACTKConfig: CTKConfig{
|
||||||
contents, err := tomlConfig.ToTomlString()
|
Path: nvidiaCTKExecutable,
|
||||||
if err != nil {
|
},
|
||||||
return nil, err
|
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
||||||
}
|
DebugFilePath: "/dev/null",
|
||||||
|
LogLevel: "info",
|
||||||
reloaded, err := toml.Load(contents)
|
Runtimes: []string{"docker-runc", "runc"},
|
||||||
if err != nil {
|
Mode: "auto",
|
||||||
return nil, err
|
Modes: modesConfig{
|
||||||
}
|
CSV: csvModeConfig{
|
||||||
|
MountSpecPath: "/etc/nvidia-container-runtime/host-files-for-container.d",
|
||||||
d := Config{}
|
},
|
||||||
if err := reloaded.Unmarshal(&d); err != nil {
|
CDI: cdiModeConfig{
|
||||||
return nil, fmt.Errorf("failed to unmarshal config: %v", err)
|
DefaultKind: "nvidia.com/gpu",
|
||||||
}
|
AnnotationPrefixes: []string{cdi.AnnotationPrefix},
|
||||||
|
},
|
||||||
// The default value for the accept-nvidia-visible-devices-envvar-when-unprivileged is non-standard.
|
},
|
||||||
// As such we explicitly handle it being set here.
|
},
|
||||||
if reloaded.Get("accept-nvidia-visible-devices-envvar-when-unprivileged") == nil {
|
NVIDIAContainerRuntimeHookConfig: RuntimeHookConfig{
|
||||||
d.AcceptEnvvarUnprivileged = true
|
Path: NVIDIAContainerRuntimeHookExecutable,
|
||||||
}
|
},
|
||||||
// The default value for the nvidia-container-runtime.debug is non-standard.
|
|
||||||
// As such we explicitly handle it being set here.
|
|
||||||
if reloaded.Get("nvidia-container-runtime.debug") == nil {
|
|
||||||
d.NVIDIAContainerRuntimeConfig.DebugFilePath = "/dev/null"
|
|
||||||
}
|
}
|
||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultToml returns the default config as a toml Tree.
|
|
||||||
func GetDefaultToml() (*toml.Tree, error) {
|
|
||||||
tree, err := toml.TreeFromMap(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tree.Set("disable-require", false)
|
|
||||||
tree.SetWithComment("swarm-resource", "", true, "DOCKER_RESOURCE_GPU")
|
|
||||||
tree.SetWithComment("accept-nvidia-visible-devices-envvar-when-unprivileged", "", true, true)
|
|
||||||
tree.SetWithComment("accept-nvidia-visible-devices-as-volume-mounts", "", true, false)
|
|
||||||
|
|
||||||
// nvidia-container-cli
|
|
||||||
tree.SetWithComment("nvidia-container-cli.root", "", true, "/run/nvidia/driver")
|
|
||||||
tree.SetWithComment("nvidia-container-cli.path", "", true, "/usr/bin/nvidia-container-cli")
|
|
||||||
tree.Set("nvidia-container-cli.environment", []string{})
|
|
||||||
tree.SetWithComment("nvidia-container-cli.debug", "", true, "/var/log/nvidia-container-toolkit.log")
|
|
||||||
tree.SetWithComment("nvidia-container-cli.ldcache", "", true, "/etc/ld.so.cache")
|
|
||||||
tree.Set("nvidia-container-cli.load-kmods", true)
|
|
||||||
tree.SetWithComment("nvidia-container-cli.no-cgroups", "", true, false)
|
|
||||||
|
|
||||||
tree.SetWithComment("nvidia-container-cli.user", "", getCommentedUserGroup(), getUserGroup())
|
|
||||||
tree.Set("nvidia-container-cli.ldconfig", getLdConfigPath())
|
|
||||||
|
|
||||||
// nvidia-container-runtime
|
|
||||||
tree.SetWithComment("nvidia-container-runtime.debug", "", true, "/var/log/nvidia-container-runtime.log")
|
|
||||||
tree.Set("nvidia-container-runtime.log-level", "info")
|
|
||||||
|
|
||||||
commentLines := []string{
|
|
||||||
"Specify the runtimes to consider. This list is processed in order and the PATH",
|
|
||||||
"searched for matching executables unless the entry is an absolute path.",
|
|
||||||
}
|
|
||||||
tree.SetWithComment("nvidia-container-runtime.runtimes", strings.Join(commentLines, "\n "), false, []string{"docker-runc", "runc"})
|
|
||||||
|
|
||||||
tree.Set("nvidia-container-runtime.mode", "auto")
|
|
||||||
|
|
||||||
tree.Set("nvidia-container-runtime.modes.csv.mount-spec-path", "/etc/nvidia-container-runtime/host-files-for-container.d")
|
|
||||||
tree.Set("nvidia-container-runtime.modes.cdi.default-kind", "nvidia.com/gpu")
|
|
||||||
tree.Set("nvidia-container-runtime.modes.cdi.annotation-prefixes", []string{cdi.AnnotationPrefix})
|
|
||||||
|
|
||||||
// nvidia-ctk
|
|
||||||
tree.Set("nvidia-ctk.path", nvidiaCTKExecutable)
|
|
||||||
|
|
||||||
// nvidia-container-runtime-hook
|
|
||||||
tree.Set("nvidia-container-runtime-hook.path", nvidiaContainerRuntimeHookExecutable)
|
|
||||||
|
|
||||||
return tree, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLdConfigPath() string {
|
func getLdConfigPath() string {
|
||||||
if _, err := os.Stat("/sbin/ldconfig.real"); err == nil {
|
if _, err := os.Stat("/sbin/ldconfig.real"); err == nil {
|
||||||
return "@/sbin/ldconfig.real"
|
return "@/sbin/ldconfig.real"
|
||||||
@ -221,11 +168,6 @@ func getLdConfigPath() string {
|
|||||||
return "@/sbin/ldconfig"
|
return "@/sbin/ldconfig"
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUserGroup returns the user and group to use for the nvidia-container-cli and whether the config option should be commented.
|
|
||||||
func getUserGroup() string {
|
|
||||||
return "root:video"
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCommentedUserGroup returns whether the nvidia-container-cli user and group config option should be commented.
|
// getCommentedUserGroup returns whether the nvidia-container-cli user and group config option should be commented.
|
||||||
func getCommentedUserGroup() bool {
|
func getCommentedUserGroup() bool {
|
||||||
uncommentIf := map[string]bool{
|
uncommentIf := map[string]bool{
|
||||||
@ -311,3 +253,66 @@ func resolveWithDefault(logger logger.Interface, label string, path string, defa
|
|||||||
|
|
||||||
return resolvedPath
|
return resolvedPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) asCommentedToml() (*toml.Tree, error) {
|
||||||
|
contents, err := toml.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
asToml, err := toml.LoadBytes(contents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
commentedDefaults := map[string]interface{}{
|
||||||
|
"swarm-resource": "DOCKER_RESOURCE_GPU",
|
||||||
|
"accept-nvidia-visible-devices-envvar-when-unprivileged": true,
|
||||||
|
"accept-nvidia-visible-devices-as-volume-mounts": false,
|
||||||
|
"nvidia-container-cli.root": "/run/nvidia/driver",
|
||||||
|
"nvidia-container-cli.path": "/usr/bin/nvidia-container-cli",
|
||||||
|
"nvidia-container-cli.debug": "/var/log/nvidia-container-toolkit.log",
|
||||||
|
"nvidia-container-cli.ldcache": "/etc/ld.so.cache",
|
||||||
|
"nvidia-container-cli.no-cgroups": false,
|
||||||
|
"nvidia-container-cli.user": "root:video",
|
||||||
|
"nvidia-container-runtime.debug": "/var/log/nvidia-container-runtime.log",
|
||||||
|
}
|
||||||
|
for k, v := range commentedDefaults {
|
||||||
|
set := asToml.Get(k)
|
||||||
|
fmt.Printf("k=%v v=%+v set=%+v\n", k, v, set)
|
||||||
|
if !shouldComment(k, v, set) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("set=%+v v=%+v\n", set, v)
|
||||||
|
asToml.SetWithComment(k, "", true, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return asToml, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldComment(key string, value interface{}, set interface{}) bool {
|
||||||
|
if key == "nvidia-container-cli.user" && !getCommentedUserGroup() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if key == "nvidia-container-runtime.debug" && set == "/dev/null" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if set == nil || value == set {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save writes the config to the specified writer.
|
||||||
|
func (c Config) Save(w io.Writer) (int64, error) {
|
||||||
|
asToml, err := c.asCommentedToml()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := toml.NewEncoder(w).Indentation("")
|
||||||
|
if err := enc.Encode(asToml); err != nil {
|
||||||
|
return 0, fmt.Errorf("invalid config: %v", err)
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
@ -49,17 +49,21 @@ func TestGetConfigWithCustomConfig(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetConfig(t *testing.T) {
|
func TestGetConfig(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
contents []string
|
contents []string
|
||||||
expectedError error
|
expectedError error
|
||||||
expectedConfig *Config
|
inspectLdconfig bool
|
||||||
|
expectedConfig *Config
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "empty config is default",
|
description: "empty config is default",
|
||||||
|
inspectLdconfig: true,
|
||||||
expectedConfig: &Config{
|
expectedConfig: &Config{
|
||||||
AcceptEnvvarUnprivileged: true,
|
AcceptEnvvarUnprivileged: true,
|
||||||
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
||||||
Root: "",
|
Root: "",
|
||||||
|
LoadKmods: true,
|
||||||
|
Ldconfig: "WAS_CHECKED",
|
||||||
},
|
},
|
||||||
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
||||||
DebugFilePath: "/dev/null",
|
DebugFilePath: "/dev/null",
|
||||||
@ -89,6 +93,8 @@ func TestGetConfig(t *testing.T) {
|
|||||||
contents: []string{
|
contents: []string{
|
||||||
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
|
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
|
||||||
"nvidia-container-cli.root = \"/bar/baz\"",
|
"nvidia-container-cli.root = \"/bar/baz\"",
|
||||||
|
"nvidia-container-cli.load-kmods = false",
|
||||||
|
"nvidia-container-cli.ldconfig = \"/foo/bar/ldconfig\"",
|
||||||
"nvidia-container-runtime.debug = \"/foo/bar\"",
|
"nvidia-container-runtime.debug = \"/foo/bar\"",
|
||||||
"nvidia-container-runtime.experimental = true",
|
"nvidia-container-runtime.experimental = true",
|
||||||
"nvidia-container-runtime.discover-mode = \"not-legacy\"",
|
"nvidia-container-runtime.discover-mode = \"not-legacy\"",
|
||||||
@ -104,7 +110,9 @@ func TestGetConfig(t *testing.T) {
|
|||||||
expectedConfig: &Config{
|
expectedConfig: &Config{
|
||||||
AcceptEnvvarUnprivileged: false,
|
AcceptEnvvarUnprivileged: false,
|
||||||
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
||||||
Root: "/bar/baz",
|
Root: "/bar/baz",
|
||||||
|
LoadKmods: false,
|
||||||
|
Ldconfig: "/foo/bar/ldconfig",
|
||||||
},
|
},
|
||||||
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
||||||
DebugFilePath: "/foo/bar",
|
DebugFilePath: "/foo/bar",
|
||||||
@ -138,6 +146,8 @@ func TestGetConfig(t *testing.T) {
|
|||||||
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
|
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
|
||||||
"[nvidia-container-cli]",
|
"[nvidia-container-cli]",
|
||||||
"root = \"/bar/baz\"",
|
"root = \"/bar/baz\"",
|
||||||
|
"load-kmods = false",
|
||||||
|
"ldconfig = \"/foo/bar/ldconfig\"",
|
||||||
"[nvidia-container-runtime]",
|
"[nvidia-container-runtime]",
|
||||||
"debug = \"/foo/bar\"",
|
"debug = \"/foo/bar\"",
|
||||||
"experimental = true",
|
"experimental = true",
|
||||||
@ -158,7 +168,9 @@ func TestGetConfig(t *testing.T) {
|
|||||||
expectedConfig: &Config{
|
expectedConfig: &Config{
|
||||||
AcceptEnvvarUnprivileged: false,
|
AcceptEnvvarUnprivileged: false,
|
||||||
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
NVIDIAContainerCLIConfig: ContainerCLIConfig{
|
||||||
Root: "/bar/baz",
|
Root: "/bar/baz",
|
||||||
|
LoadKmods: false,
|
||||||
|
Ldconfig: "/foo/bar/ldconfig",
|
||||||
},
|
},
|
||||||
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
NVIDIAContainerRuntimeConfig: RuntimeConfig{
|
||||||
DebugFilePath: "/foo/bar",
|
DebugFilePath: "/foo/bar",
|
||||||
@ -199,6 +211,16 @@ func TestGetConfig(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We first handle the ldconfig path since this is currently system-dependent.
|
||||||
|
if tc.inspectLdconfig {
|
||||||
|
ldconfig := cfg.NVIDIAContainerCLIConfig.Ldconfig
|
||||||
|
require.True(t, strings.HasPrefix(ldconfig, "@/sbin/ldconfig"))
|
||||||
|
remaining := strings.TrimPrefix(ldconfig, "@/sbin/ldconfig")
|
||||||
|
require.True(t, remaining == ".real" || remaining == "")
|
||||||
|
|
||||||
|
cfg.NVIDIAContainerCLIConfig.Ldconfig = "WAS_CHECKED"
|
||||||
|
}
|
||||||
|
|
||||||
require.EqualValues(t, tc.expectedConfig, cfg)
|
require.EqualValues(t, tc.expectedConfig, cfg)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user