Skip to content

Commit 8188b55

Browse files
authored
Merge pull request #1382 from elezar/fix-bug-in-handling-existing-imports
Fix handling of existing imports in containerd
2 parents c7e8d22 + 40c3a75 commit 8188b55

File tree

3 files changed

+131
-4
lines changed

3 files changed

+131
-4
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,36 @@ func TestConfigureLifecycle(t *testing.T) {
4343
assertConditions func(*testing.T, string) error
4444
}{
4545
// Containerd v2 test cases
46+
{
47+
description: "containerd: config exists with imports",
48+
args: []string{
49+
"--runtime", "containerd",
50+
"--config", "{{ .testRoot }}/etc/containerd/config.toml",
51+
"--drop-in-config", "{{ .testRoot }}/etc/containerd/conf.d/99-nvidia.toml",
52+
},
53+
prepareEnvironment: func(t *testing.T, testRoot string) error {
54+
configPath := filepath.Join(testRoot, "etc/containerd/config.toml")
55+
require.NoError(t, os.MkdirAll(filepath.Dir(configPath), 0755))
56+
57+
initialConfig := `version = 2
58+
imports = ["/foo/bar/*.toml"]
59+
`
60+
return os.WriteFile(configPath, []byte(initialConfig), 0600)
61+
},
62+
assertConditions: func(t *testing.T, testRoot string) error {
63+
mainConfig := filepath.Join(testRoot, "etc/containerd/config.toml")
64+
content, err := os.ReadFile(mainConfig)
65+
require.NoError(t, err)
66+
67+
expectedTemplate := `imports = ["/foo/bar/*.toml", "{{ .testRoot }}/etc/containerd/conf.d/*.toml"]
68+
version = 2
69+
`
70+
expected := strings.ReplaceAll(expectedTemplate, "{{ .testRoot }}", testRoot)
71+
72+
require.Equal(t, expected, string(content))
73+
return nil
74+
},
75+
},
4676
{
4777
description: "containerd: v2 config does not exist with drop-in",
4878
args: []string{

pkg/config/engine/containerd/config_drop_in.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,35 @@ func (c *topLevelConfig) removeVersion() {
173173
c.config.Delete("version")
174174
}
175175

176+
func (c *topLevelConfig) getCurrentImports() []string {
177+
rawImports := c.config.Get("imports")
178+
if rawImports == nil {
179+
return nil
180+
}
181+
182+
if importsStringSlice, ok := rawImports.([]string); ok {
183+
return importsStringSlice
184+
}
185+
186+
importsAnySlice, ok := rawImports.([]any)
187+
if !ok {
188+
return nil
189+
}
190+
var importsStringSlice []string
191+
for _, importAny := range importsAnySlice {
192+
importString, ok := importAny.(string)
193+
if !ok {
194+
continue
195+
}
196+
importsStringSlice = append(importsStringSlice, importString)
197+
}
198+
199+
return importsStringSlice
200+
}
201+
176202
func (c *topLevelConfig) ensureImports(dropInFilename string) {
177203
config := c.config.Tree
178-
var currentImports []string
179-
if ci, ok := c.config.Get("imports").([]string); ok {
180-
currentImports = ci
181-
}
204+
currentImports := c.getCurrentImports()
182205

183206
requiredImport := c.importPattern(dropInFilename)
184207
for _, currentImport := range currentImports {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
**/
17+
18+
package containerd
19+
20+
import (
21+
"testing"
22+
23+
"github.com/stretchr/testify/require"
24+
25+
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
26+
)
27+
28+
func TestEnsureImports(t *testing.T) {
29+
testCases := []struct {
30+
description string
31+
configMap map[string]any
32+
path string
33+
expectedImports []string
34+
}{
35+
{
36+
description: "empty",
37+
path: "/another/path/file.toml",
38+
expectedImports: []string{"/another/path/*.toml"},
39+
},
40+
{
41+
description: "existing imports as string slice",
42+
configMap: map[string]any{
43+
"imports": []string{"/foo/bar/*.toml"},
44+
},
45+
path: "/another/path/file.toml",
46+
expectedImports: []string{"/foo/bar/*.toml", "/another/path/*.toml"},
47+
},
48+
{
49+
description: "existing imports as any slice",
50+
configMap: map[string]any{
51+
"imports": []any{"/foo/bar/*.toml"},
52+
},
53+
path: "/another/path/file.toml",
54+
expectedImports: []string{"/foo/bar/*.toml", "/another/path/*.toml"},
55+
},
56+
}
57+
58+
for _, tc := range testCases {
59+
t.Run(tc.description, func(t *testing.T) {
60+
cut := topLevelConfig{
61+
config: &Config{
62+
Tree: func() *toml.Tree {
63+
t, _ := toml.FromMap(tc.configMap).Load()
64+
return t
65+
}(),
66+
},
67+
}
68+
69+
cut.ensureImports("/another/path/file.toml")
70+
require.EqualValues(t, tc.expectedImports, cut.config.Get("imports"))
71+
})
72+
}
73+
74+
}

0 commit comments

Comments
 (0)