Skip to content

Commit 7d35de4

Browse files
committed
fetch current container runtime config through the command line
Signed-off-by: Tariq Ibrahim <[email protected]> add default runtime binary path to runtimes field of toolkit config toml Signed-off-by: Tariq Ibrahim <[email protected]>
1 parent 19482da commit 7d35de4

File tree

15 files changed

+370
-30
lines changed

15 files changed

+370
-30
lines changed

.golangci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ linters:
1818
linters-settings:
1919
goimports:
2020
local-prefixes: github.com/NVIDIA/nvidia-container-toolkit
21+
gosec:
22+
excludes:
23+
# TODO: Consider hardening security of command line invocations
24+
- G204
2125

2226
issues:
2327
exclude:

cmd/nvidia-ctk/runtime/configure/configure.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const (
4444
defaultContainerdConfigFilePath = "/etc/containerd/config.toml"
4545
defaultCrioConfigFilePath = "/etc/crio/crio.conf"
4646
defaultDockerConfigFilePath = "/etc/docker/daemon.json"
47+
48+
runtimeContainerd = "containerd"
49+
runtimeCrio = "crio"
50+
runtimeDocker = "docker"
4751
)
4852

4953
type command struct {
@@ -174,14 +178,14 @@ func (m command) validateFlags(c *cli.Context, config *config) error {
174178
config.mode = "config-file"
175179

176180
switch config.runtime {
177-
case "containerd", "crio", "docker":
181+
case runtimeContainerd, runtimeCrio, runtimeDocker:
178182
break
179183
default:
180184
return fmt.Errorf("unrecognized runtime '%v'", config.runtime)
181185
}
182186

183187
switch config.runtime {
184-
case "containerd", "crio":
188+
case runtimeContainerd, runtimeCrio:
185189
if config.nvidiaRuntime.path == defaultNVIDIARuntimeExecutable {
186190
config.nvidiaRuntime.path = defaultNVIDIARuntimeExpecutablePath
187191
}
@@ -190,7 +194,7 @@ func (m command) validateFlags(c *cli.Context, config *config) error {
190194
}
191195
}
192196

193-
if config.runtime != "containerd" && config.runtime != "docker" {
197+
if config.runtime != runtimeContainerd && config.runtime != runtimeDocker {
194198
if config.cdi.enabled {
195199
m.logger.Warningf("Ignoring cdi.enabled flag for %v", config.runtime)
196200
}
@@ -219,23 +223,24 @@ func (m command) configureWrapper(c *cli.Context, config *config) error {
219223
// configureConfigFile updates the specified container engine config file to enable the NVIDIA runtime.
220224
func (m command) configureConfigFile(c *cli.Context, config *config) error {
221225
configFilePath := config.resolveConfigFilePath()
226+
configCommand := config.resolveConfigCommand()
222227

223228
var cfg engine.Interface
224229
var err error
225230
switch config.runtime {
226-
case "containerd":
231+
case runtimeContainerd:
227232
cfg, err = containerd.New(
228233
containerd.WithLogger(m.logger),
229234
containerd.WithPath(configFilePath),
230-
containerd.WithConfigSource(toml.FromFile(configFilePath)),
235+
containerd.WithConfigSource(toml.FromCommandLine(configCommand)),
231236
)
232-
case "crio":
237+
case runtimeCrio:
233238
cfg, err = crio.New(
234239
crio.WithLogger(m.logger),
235240
crio.WithPath(configFilePath),
236-
crio.WithConfigSource(toml.FromFile(configFilePath)),
241+
crio.WithConfigSource(toml.FromCommandLine(configCommand)),
237242
)
238-
case "docker":
243+
case runtimeDocker:
239244
cfg, err = docker.New(
240245
docker.WithLogger(m.logger),
241246
docker.WithPath(configFilePath),
@@ -285,16 +290,27 @@ func (c *config) resolveConfigFilePath() string {
285290
return c.configFilePath
286291
}
287292
switch c.runtime {
288-
case "containerd":
293+
case runtimeContainerd:
289294
return defaultContainerdConfigFilePath
290-
case "crio":
295+
case runtimeCrio:
291296
return defaultCrioConfigFilePath
292-
case "docker":
297+
case runtimeDocker:
293298
return defaultDockerConfigFilePath
294299
}
295300
return ""
296301
}
297302

303+
// resolveConfigCommand returns the default cli command to fetch the current runtime config
304+
func (c *config) resolveConfigCommand() []string {
305+
switch c.runtime {
306+
case runtimeContainerd:
307+
return []string{"containerd", "config", "dump"}
308+
case runtimeCrio:
309+
return []string{"crio", "status", "config"}
310+
}
311+
return []string{}
312+
}
313+
298314
// getOuputConfigPath returns the configured config path or "" if dry-run is enabled
299315
func (c *config) getOuputConfigPath() string {
300316
if c.dryRun {
@@ -318,9 +334,9 @@ func enableCDI(config *config, cfg engine.Interface) error {
318334
return nil
319335
}
320336
switch config.runtime {
321-
case "containerd":
337+
case runtimeContainerd:
322338
cfg.Set("enable_cdi", true)
323-
case "docker":
339+
case runtimeDocker:
324340
cfg.Set("features", map[string]bool{"cdi": true})
325341
default:
326342
return fmt.Errorf("enabling CDI in %s is not supported", config.runtime)

internal/config/toml.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,26 @@ func (t *Toml) Get(key string) interface{} {
170170
return (*toml.Tree)(t).Get(key)
171171
}
172172

173+
// GetDefault returns the value for the specified key and falls back to the default value if the Get call fails
174+
func (t *Toml) GetDefault(key string, def interface{}) interface{} {
175+
val := t.Get(key)
176+
if val == nil {
177+
return def
178+
}
179+
return val
180+
}
181+
173182
// Set sets the specified key to the specified value in the TOML config.
174183
func (t *Toml) Set(key string, value interface{}) {
175184
(*toml.Tree)(t).Set(key, value)
176185
}
177186

187+
// WriteTo encode the Tree as Toml and writes it to the writer w.
188+
// Returns the number of bytes written in case of success, or an error if anything happened.
189+
func (t *Toml) WriteTo(w io.Writer) (int64, error) {
190+
return (*toml.Tree)(t).WriteTo(w)
191+
}
192+
178193
// commentDefaults applies the required comments for default values to the Toml.
179194
func (t *Toml) commentDefaults() *Toml {
180195
asToml := (*toml.Tree)(t)

pkg/config/engine/api.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ type Interface interface {
2323
Set(string, interface{})
2424
RemoveRuntime(string) error
2525
Save(string) (int64, error)
26+
GetRuntimeConfig(string) (RuntimeConfig, error)
27+
}
28+
29+
// RuntimeConfig defines the interface to query container runtime handler configuration
30+
type RuntimeConfig interface {
31+
GetBinPath() string
2632
}

pkg/config/engine/containerd/config_v1.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,25 @@ import (
2222
"github.com/pelletier/go-toml"
2323

2424
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
25+
cfgtoml "github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
2526
)
2627

2728
// ConfigV1 represents a version 1 containerd config
2829
type ConfigV1 Config
2930

3031
var _ engine.Interface = (*ConfigV1)(nil)
3132

33+
type ctrdCfgV1Runtime struct {
34+
tree *cfgtoml.Tree
35+
}
36+
37+
func (c *ctrdCfgV1Runtime) GetBinPath() string {
38+
if binPath, ok := c.tree.GetPath([]string{"options", "BinaryName"}).(string); ok {
39+
return binPath
40+
}
41+
return ""
42+
}
43+
3244
// AddRuntime adds a runtime to the containerd config
3345
func (c *ConfigV1) AddRuntime(name string, path string, setAsDefault bool) error {
3446
if c == nil || c.Tree == nil {
@@ -146,6 +158,18 @@ func (c *ConfigV1) RemoveRuntime(name string) error {
146158
return nil
147159
}
148160

161+
func (c *ConfigV1) GetRuntime(name string) (interface{}, error) {
162+
if c == nil || c.Tree == nil {
163+
return nil, fmt.Errorf("config is nil")
164+
}
165+
config := *c.Tree
166+
runtimeData, ok := config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", name}).(*toml.Tree)
167+
if !ok {
168+
return nil, fmt.Errorf("invalid toml object")
169+
}
170+
return runtimeData, nil
171+
}
172+
149173
// SetOption sets the specified containerd option.
150174
func (c *ConfigV1) Set(key string, value interface{}) {
151175
config := *c.Tree
@@ -157,3 +181,15 @@ func (c *ConfigV1) Set(key string, value interface{}) {
157181
func (c ConfigV1) Save(path string) (int64, error) {
158182
return (Config)(c).Save(path)
159183
}
184+
185+
func (c *ConfigV1) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
186+
if c == nil || c.Tree == nil {
187+
return nil, fmt.Errorf("config is nil")
188+
}
189+
config := *c.Tree
190+
runtimeData := config.GetSubtreeByPath([]string{"plugins", "cri", "containerd", "runtimes", name})
191+
192+
return &ctrdCfgV1Runtime{
193+
tree: runtimeData,
194+
}, nil
195+
}

pkg/config/engine/containerd/config_v2.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ import (
2222
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
2323
)
2424

25+
type ctrdCfgV2Runtime struct {
26+
tree *toml.Tree
27+
}
28+
29+
func (c *ctrdCfgV2Runtime) GetBinPath() string {
30+
if binPath, ok := c.tree.GetPath([]string{"options", "BinaryName"}).(string); ok {
31+
return binPath
32+
}
33+
return ""
34+
}
35+
2536
// AddRuntime adds a runtime to the containerd config
2637
func (c *Config) AddRuntime(name string, path string, setAsDefault bool) error {
2738
if c == nil || c.Tree == nil {

pkg/config/engine/containerd/containerd.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,14 @@ func (c *Config) parseVersion(useLegacyConfig bool) (int, error) {
9898
return -1, fmt.Errorf("unsupported type for version field: %v", v)
9999
}
100100
}
101+
102+
func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
103+
if c == nil || c.Tree == nil {
104+
return nil, fmt.Errorf("config is nil")
105+
}
106+
config := *c.Tree
107+
runtimeData := config.GetSubtreeByPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", name})
108+
return &ctrdCfgV2Runtime{
109+
tree: runtimeData,
110+
}, nil
111+
}

pkg/config/engine/crio/crio.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ type Config struct {
3030
Logger logger.Interface
3131
}
3232

33+
type crioRuntime struct {
34+
tree *toml.Tree
35+
}
36+
37+
func (c *crioRuntime) GetBinPath() string {
38+
if binaryPath, ok := c.tree.GetPath([]string{"runtime_path"}).(string); ok && binaryPath != "" {
39+
return binaryPath
40+
}
41+
return ""
42+
}
43+
3344
var _ engine.Interface = (*Config)(nil)
3445

3546
// New creates a cri-o config with the specified options
@@ -66,10 +77,11 @@ func (c *Config) AddRuntime(name string, path string, setAsDefault bool) error {
6677
config := *c.Tree
6778

6879
// By default we extract the runtime options from the runc settings; if this does not exist we get the options from the default runtime specified in the config.
69-
runtimeNamesForConfig := []string{"runc"}
80+
var runtimeNamesForConfig []string
7081
if name, ok := config.GetPath([]string{"crio", "runtime", "default_runtime"}).(string); ok && name != "" {
7182
runtimeNamesForConfig = append(runtimeNamesForConfig, name)
7283
}
84+
runtimeNamesForConfig = append(runtimeNamesForConfig, "runc")
7385
for _, r := range runtimeNamesForConfig {
7486
if options, ok := config.GetPath([]string{"crio", "runtime", "runtimes", r}).(*toml.Tree); ok {
7587
c.Logger.Debugf("using options from runtime %v: %v", r, options.String())
@@ -129,3 +141,14 @@ func (c *Config) RemoveRuntime(name string) error {
129141
*c.Tree = config
130142
return nil
131143
}
144+
145+
func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
146+
if c == nil || c.Tree == nil {
147+
return nil, fmt.Errorf("config is nil")
148+
}
149+
config := *c.Tree
150+
runtimeData := config.GetSubtreeByPath([]string{"crio", "runtime", "runtimes", name})
151+
return &crioRuntime{
152+
tree: runtimeData,
153+
}, nil
154+
}

pkg/config/engine/crio/crio_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func TestAddRuntime(t *testing.T) {
9191
`,
9292
},
9393
{
94-
description: "options from runc take precedence over default runtime",
94+
description: "options from runc DO NOT take precedence over default runtime",
9595
config: `
9696
[crio]
9797
[crio.runtime]
@@ -120,7 +120,7 @@ func TestAddRuntime(t *testing.T) {
120120
[crio.runtime.runtimes.test]
121121
runtime_path = "/usr/bin/test"
122122
runtime_type = "oci"
123-
runc_option = "option"
123+
default_option = "option"
124124
`,
125125
},
126126
}

pkg/config/engine/docker/docker.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package docker
1818

1919
import (
2020
"encoding/json"
21+
"errors"
2122
"fmt"
2223

2324
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
@@ -132,3 +133,29 @@ func (c Config) Save(path string) (int64, error) {
132133
n, err := config.Raw(path).Write(output)
133134
return int64(n), err
134135
}
136+
137+
// GetRuntime returns the TOML object of the runtime passed as input
138+
func (c *Config) GetRuntime(name string) (interface{}, error) {
139+
if c == nil {
140+
return nil, fmt.Errorf("config is nil")
141+
}
142+
143+
config := *c
144+
145+
var runtimes map[string]interface{}
146+
if _, exists := config["runtimes"]; exists {
147+
runtimes = config["runtimes"].(map[string]interface{})
148+
} else {
149+
return nil, fmt.Errorf("config is nil")
150+
}
151+
152+
if r, ok := runtimes[name]; ok {
153+
return r, nil
154+
} else {
155+
return nil, fmt.Errorf("runtime %s not found", name)
156+
}
157+
}
158+
159+
func (c *Config) GetRuntimeConfig(name string) (engine.RuntimeConfig, error) {
160+
return nil, errors.New("Not Implemented")
161+
}

0 commit comments

Comments
 (0)