Skip to content

Commit f78d3a8

Browse files
committed
Rework default config generation to not use toml
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent bc6ca7f commit f78d3a8

File tree

4 files changed

+125
-99
lines changed

4 files changed

+125
-99
lines changed

cmd/nvidia-ctk/config/create-default/create-default.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626

2727
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
2828
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
29-
"github.com/pelletier/go-toml"
3029
"github.com/urfave/cli/v2"
3130
)
3231

@@ -126,12 +125,10 @@ func (opts options) getFormattedConfig() ([]byte, error) {
126125
}
127126

128127
buffer := bytes.NewBuffer(nil)
129-
enc := toml.NewEncoder(buffer).Indentation("")
130128

131-
if err := enc.Encode(cfg); err != nil {
132-
return nil, fmt.Errorf("invalid config: %v", err)
129+
if _, err := cfg.Save(buffer); err != nil {
130+
return nil, fmt.Errorf("unable to save config: %v", err)
133131
}
134-
135132
return fixComments(buffer.Bytes())
136133
}
137134

internal/config/cli.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ package config
1818

1919
// ContainerCLIConfig stores the options for the nvidia-container-cli
2020
type ContainerCLIConfig struct {
21-
Root string `toml:"root"`
21+
Root string `toml:"root"`
22+
LoadKmods bool `toml:"load-kmods"`
23+
Ldconfig string `toml:"ldconfig"`
2224
}

internal/config/config.go

Lines changed: 90 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -130,102 +130,44 @@ func getFromTree(toml *toml.Tree) (*Config, error) {
130130

131131
// getDefault defines the default values for the config
132132
func getDefault() (*Config, error) {
133-
tomlConfig, err := GetDefaultToml()
134-
if err != nil {
135-
return nil, err
136-
}
137-
138-
// tomlConfig above includes information about the default values and comments.
139-
// we need to marshal it back to a string and then unmarshal it to strip the comments.
140-
contents, err := tomlConfig.ToTomlString()
141-
if err != nil {
142-
return nil, err
143-
}
144-
145-
reloaded, err := toml.Load(contents)
146-
if err != nil {
147-
return nil, err
148-
}
149-
150-
d := Config{}
151-
if err := reloaded.Unmarshal(&d); err != nil {
152-
return nil, fmt.Errorf("failed to unmarshal config: %v", err)
153-
}
154-
155-
// The default value for the accept-nvidia-visible-devices-envvar-when-unprivileged is non-standard.
156-
// As such we explicitly handle it being set here.
157-
if reloaded.Get("accept-nvidia-visible-devices-envvar-when-unprivileged") == nil {
158-
d.AcceptEnvvarUnprivileged = true
159-
}
160-
// The default value for the nvidia-container-runtime.debug is non-standard.
161-
// As such we explicitly handle it being set here.
162-
if reloaded.Get("nvidia-container-runtime.debug") == nil {
163-
d.NVIDIAContainerRuntimeConfig.DebugFilePath = "/dev/null"
133+
d := Config{
134+
AcceptEnvvarUnprivileged: true,
135+
NVIDIAContainerCLIConfig: ContainerCLIConfig{
136+
LoadKmods: true,
137+
Ldconfig: getLdConfigPath(),
138+
},
139+
NVIDIACTKConfig: CTKConfig{
140+
Path: nvidiaCTKExecutable,
141+
},
142+
NVIDIAContainerRuntimeConfig: RuntimeConfig{
143+
DebugFilePath: "/dev/null",
144+
LogLevel: "info",
145+
Runtimes: []string{"docker-runc", "runc"},
146+
Mode: "auto",
147+
Modes: modesConfig{
148+
CSV: csvModeConfig{
149+
MountSpecPath: "/etc/nvidia-container-runtime/host-files-for-container.d",
150+
},
151+
CDI: cdiModeConfig{
152+
DefaultKind: "nvidia.com/gpu",
153+
AnnotationPrefixes: []string{cdi.AnnotationPrefix},
154+
},
155+
},
156+
},
157+
NVIDIAContainerRuntimeHookConfig: RuntimeHookConfig{
158+
Path: NVIDIAContainerRuntimeHookExecutable,
159+
},
164160
}
165161
return &d, nil
166162
}
167163

168-
// GetDefaultToml returns the default config as a toml Tree.
169-
func GetDefaultToml() (*toml.Tree, error) {
170-
tree, err := toml.TreeFromMap(nil)
171-
if err != nil {
172-
return nil, err
173-
}
174-
175-
tree.Set("disable-require", false)
176-
tree.SetWithComment("swarm-resource", "", true, "DOCKER_RESOURCE_GPU")
177-
tree.SetWithComment("accept-nvidia-visible-devices-envvar-when-unprivileged", "", true, true)
178-
tree.SetWithComment("accept-nvidia-visible-devices-as-volume-mounts", "", true, false)
179-
180-
// nvidia-container-cli
181-
tree.SetWithComment("nvidia-container-cli.root", "", true, "/run/nvidia/driver")
182-
tree.SetWithComment("nvidia-container-cli.path", "", true, "/usr/bin/nvidia-container-cli")
183-
tree.Set("nvidia-container-cli.environment", []string{})
184-
tree.SetWithComment("nvidia-container-cli.debug", "", true, "/var/log/nvidia-container-toolkit.log")
185-
tree.SetWithComment("nvidia-container-cli.ldcache", "", true, "/etc/ld.so.cache")
186-
tree.Set("nvidia-container-cli.load-kmods", true)
187-
tree.SetWithComment("nvidia-container-cli.no-cgroups", "", true, false)
188-
189-
tree.SetWithComment("nvidia-container-cli.user", "", getCommentedUserGroup(), getUserGroup())
190-
tree.Set("nvidia-container-cli.ldconfig", getLdConfigPath())
191-
192-
// nvidia-container-runtime
193-
tree.SetWithComment("nvidia-container-runtime.debug", "", true, "/var/log/nvidia-container-runtime.log")
194-
tree.Set("nvidia-container-runtime.log-level", "info")
195-
196-
commentLines := []string{
197-
"Specify the runtimes to consider. This list is processed in order and the PATH",
198-
"searched for matching executables unless the entry is an absolute path.",
199-
}
200-
tree.SetWithComment("nvidia-container-runtime.runtimes", strings.Join(commentLines, "\n "), false, []string{"docker-runc", "runc"})
201-
202-
tree.Set("nvidia-container-runtime.mode", "auto")
203-
204-
tree.Set("nvidia-container-runtime.modes.csv.mount-spec-path", "/etc/nvidia-container-runtime/host-files-for-container.d")
205-
tree.Set("nvidia-container-runtime.modes.cdi.default-kind", "nvidia.com/gpu")
206-
tree.Set("nvidia-container-runtime.modes.cdi.annotation-prefixes", []string{cdi.AnnotationPrefix})
207-
208-
// nvidia-ctk
209-
tree.Set("nvidia-ctk.path", nvidiaCTKExecutable)
210-
211-
// nvidia-container-runtime-hook
212-
tree.Set("nvidia-container-runtime-hook.path", nvidiaContainerRuntimeHookExecutable)
213-
214-
return tree, nil
215-
}
216-
217164
func getLdConfigPath() string {
218165
if _, err := os.Stat("/sbin/ldconfig.real"); err == nil {
219166
return "@/sbin/ldconfig.real"
220167
}
221168
return "@/sbin/ldconfig"
222169
}
223170

224-
// getUserGroup returns the user and group to use for the nvidia-container-cli and whether the config option should be commented.
225-
func getUserGroup() string {
226-
return "root:video"
227-
}
228-
229171
// getCommentedUserGroup returns whether the nvidia-container-cli user and group config option should be commented.
230172
func getCommentedUserGroup() bool {
231173
uncommentIf := map[string]bool{
@@ -311,3 +253,66 @@ func resolveWithDefault(logger logger.Interface, label string, path string, defa
311253

312254
return resolvedPath
313255
}
256+
257+
func (c Config) asCommentedToml() (*toml.Tree, error) {
258+
contents, err := toml.Marshal(c)
259+
if err != nil {
260+
return nil, err
261+
}
262+
asToml, err := toml.LoadBytes(contents)
263+
if err != nil {
264+
return nil, err
265+
}
266+
267+
commentedDefaults := map[string]interface{}{
268+
"swarm-resource": "DOCKER_RESOURCE_GPU",
269+
"accept-nvidia-visible-devices-envvar-when-unprivileged": true,
270+
"accept-nvidia-visible-devices-as-volume-mounts": false,
271+
"nvidia-container-cli.root": "/run/nvidia/driver",
272+
"nvidia-container-cli.path": "/usr/bin/nvidia-container-cli",
273+
"nvidia-container-cli.debug": "/var/log/nvidia-container-toolkit.log",
274+
"nvidia-container-cli.ldcache": "/etc/ld.so.cache",
275+
"nvidia-container-cli.no-cgroups": false,
276+
"nvidia-container-cli.user": "root:video",
277+
"nvidia-container-runtime.debug": "/var/log/nvidia-container-runtime.log",
278+
}
279+
for k, v := range commentedDefaults {
280+
set := asToml.Get(k)
281+
fmt.Printf("k=%v v=%+v set=%+v\n", k, v, set)
282+
if !shouldComment(k, v, set) {
283+
continue
284+
}
285+
fmt.Printf("set=%+v v=%+v\n", set, v)
286+
asToml.SetWithComment(k, "", true, v)
287+
}
288+
289+
return asToml, nil
290+
}
291+
292+
func shouldComment(key string, value interface{}, set interface{}) bool {
293+
if key == "nvidia-container-cli.user" && !getCommentedUserGroup() {
294+
return false
295+
}
296+
if key == "nvidia-container-runtime.debug" && set == "/dev/null" {
297+
return true
298+
}
299+
if set == nil || value == set {
300+
return true
301+
}
302+
303+
return false
304+
}
305+
306+
// Save writes the config to the specified writer.
307+
func (c Config) Save(w io.Writer) (int64, error) {
308+
asToml, err := c.asCommentedToml()
309+
if err != nil {
310+
return 0, err
311+
}
312+
313+
enc := toml.NewEncoder(w).Indentation("")
314+
if err := enc.Encode(asToml); err != nil {
315+
return 0, fmt.Errorf("invalid config: %v", err)
316+
}
317+
return 0, nil
318+
}

internal/config/config_test.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,21 @@ func TestGetConfigWithCustomConfig(t *testing.T) {
4949

5050
func TestGetConfig(t *testing.T) {
5151
testCases := []struct {
52-
description string
53-
contents []string
54-
expectedError error
55-
expectedConfig *Config
52+
description string
53+
contents []string
54+
expectedError error
55+
inspectLdconfig bool
56+
expectedConfig *Config
5657
}{
5758
{
58-
description: "empty config is default",
59+
description: "empty config is default",
60+
inspectLdconfig: true,
5961
expectedConfig: &Config{
6062
AcceptEnvvarUnprivileged: true,
6163
NVIDIAContainerCLIConfig: ContainerCLIConfig{
62-
Root: "",
64+
Root: "",
65+
LoadKmods: true,
66+
Ldconfig: "WAS_CHECKED",
6367
},
6468
NVIDIAContainerRuntimeConfig: RuntimeConfig{
6569
DebugFilePath: "/dev/null",
@@ -89,6 +93,8 @@ func TestGetConfig(t *testing.T) {
8993
contents: []string{
9094
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
9195
"nvidia-container-cli.root = \"/bar/baz\"",
96+
"nvidia-container-cli.load-kmods = false",
97+
"nvidia-container-cli.ldconfig = \"/foo/bar/ldconfig\"",
9298
"nvidia-container-runtime.debug = \"/foo/bar\"",
9399
"nvidia-container-runtime.experimental = true",
94100
"nvidia-container-runtime.discover-mode = \"not-legacy\"",
@@ -104,7 +110,9 @@ func TestGetConfig(t *testing.T) {
104110
expectedConfig: &Config{
105111
AcceptEnvvarUnprivileged: false,
106112
NVIDIAContainerCLIConfig: ContainerCLIConfig{
107-
Root: "/bar/baz",
113+
Root: "/bar/baz",
114+
LoadKmods: false,
115+
Ldconfig: "/foo/bar/ldconfig",
108116
},
109117
NVIDIAContainerRuntimeConfig: RuntimeConfig{
110118
DebugFilePath: "/foo/bar",
@@ -138,6 +146,8 @@ func TestGetConfig(t *testing.T) {
138146
"accept-nvidia-visible-devices-envvar-when-unprivileged = false",
139147
"[nvidia-container-cli]",
140148
"root = \"/bar/baz\"",
149+
"load-kmods = false",
150+
"ldconfig = \"/foo/bar/ldconfig\"",
141151
"[nvidia-container-runtime]",
142152
"debug = \"/foo/bar\"",
143153
"experimental = true",
@@ -158,7 +168,9 @@ func TestGetConfig(t *testing.T) {
158168
expectedConfig: &Config{
159169
AcceptEnvvarUnprivileged: false,
160170
NVIDIAContainerCLIConfig: ContainerCLIConfig{
161-
Root: "/bar/baz",
171+
Root: "/bar/baz",
172+
LoadKmods: false,
173+
Ldconfig: "/foo/bar/ldconfig",
162174
},
163175
NVIDIAContainerRuntimeConfig: RuntimeConfig{
164176
DebugFilePath: "/foo/bar",
@@ -199,6 +211,16 @@ func TestGetConfig(t *testing.T) {
199211
require.NoError(t, err)
200212
}
201213

214+
// We first handle the ldconfig path since this is currently system-dependent.
215+
if tc.inspectLdconfig {
216+
ldconfig := cfg.NVIDIAContainerCLIConfig.Ldconfig
217+
require.True(t, strings.HasPrefix(ldconfig, "@/sbin/ldconfig"))
218+
remaining := strings.TrimPrefix(ldconfig, "@/sbin/ldconfig")
219+
require.True(t, remaining == ".real" || remaining == "")
220+
221+
cfg.NVIDIAContainerCLIConfig.Ldconfig = "WAS_CHECKED"
222+
}
223+
202224
require.EqualValues(t, tc.expectedConfig, cfg)
203225
})
204226
}

0 commit comments

Comments
 (0)