Merge pull request #9982 from rayburgemeestre/merge-toml-configurations-for-plugins
Allow sections of Plugins to be merged, and not overwritten as entire sections.
This commit is contained in:
commit
deccefc8cf
@ -412,10 +412,6 @@ func mergeConfig(to, from *Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace entire sections instead of merging map's values.
|
// Replace entire sections instead of merging map's values.
|
||||||
for k, v := range from.Plugins {
|
|
||||||
to.Plugins[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range from.StreamProcessors {
|
for k, v := range from.StreamProcessors {
|
||||||
to.StreamProcessors[k] = v
|
to.StreamProcessors[k] = v
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,17 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/containerd/containerd/v2/version"
|
"github.com/containerd/containerd/v2/version"
|
||||||
@ -260,3 +265,165 @@ func TestDecodePluginInV1Config(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, true, pluginConfig["shim_debug"])
|
assert.Equal(t, true, pluginConfig["shim_debug"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergingPluginsWithTwoCriDropInConfigs(t *testing.T) {
|
||||||
|
data1 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".cni]
|
||||||
|
bin_dir = "/cm/local/apps/kubernetes/current/bin/cni"
|
||||||
|
`
|
||||||
|
data2 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||||
|
config_path = "/cm/local/apps/containerd/var/etc/certs.d"
|
||||||
|
`
|
||||||
|
expected := `
|
||||||
|
[cni]
|
||||||
|
bin_dir = '/cm/local/apps/kubernetes/current/bin/cni'
|
||||||
|
|
||||||
|
[registry]
|
||||||
|
config_path = '/cm/local/apps/containerd/var/etc/certs.d'
|
||||||
|
`
|
||||||
|
|
||||||
|
testMergeConfig(t, []string{data1, data2}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
testMergeConfig(t, []string{data2, data1}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergingPluginsWithTwoCriCniDropInConfigs(t *testing.T) {
|
||||||
|
data1 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".cni]
|
||||||
|
bin_dir = "/cm/local/apps/kubernetes/current/bin/cni"
|
||||||
|
`
|
||||||
|
data2 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".cni]
|
||||||
|
conf_dir = "/tmp"
|
||||||
|
`
|
||||||
|
expected := `
|
||||||
|
[cni]
|
||||||
|
bin_dir = '/cm/local/apps/kubernetes/current/bin/cni'
|
||||||
|
conf_dir = '/tmp'
|
||||||
|
`
|
||||||
|
testMergeConfig(t, []string{data1, data2}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergingPluginsWithTwoCriRuntimeDropInConfigs(t *testing.T) {
|
||||||
|
runcRuntime := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||||
|
runtime_type = "io.containerd.runc.v2"
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
|
||||||
|
SystemdCgroup = true
|
||||||
|
`
|
||||||
|
nvidiaRuntime := `
|
||||||
|
[plugins]
|
||||||
|
[plugins."io.containerd.grpc.v1.cri"]
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd]
|
||||||
|
default_runtime_name = "nvidia"
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
|
||||||
|
privileged_without_host_devices = false
|
||||||
|
runtime_engine = ""
|
||||||
|
runtime_root = ""
|
||||||
|
runtime_type = "io.containerd.runc.v2"
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
|
||||||
|
BinaryName = "/usr/bin/nvidia-container-runtime"
|
||||||
|
SystemdCgroup = true
|
||||||
|
`
|
||||||
|
expected := `
|
||||||
|
[containerd]
|
||||||
|
default_runtime_name = 'nvidia'
|
||||||
|
|
||||||
|
[containerd.runtimes]
|
||||||
|
[containerd.runtimes.nvidia]
|
||||||
|
privileged_without_host_devices = false
|
||||||
|
runtime_engine = ''
|
||||||
|
runtime_root = ''
|
||||||
|
runtime_type = 'io.containerd.runc.v2'
|
||||||
|
|
||||||
|
[containerd.runtimes.nvidia.options]
|
||||||
|
BinaryName = '/usr/bin/nvidia-container-runtime'
|
||||||
|
SystemdCgroup = true
|
||||||
|
|
||||||
|
[containerd.runtimes.runc]
|
||||||
|
runtime_type = 'io.containerd.runc.v2'
|
||||||
|
|
||||||
|
[containerd.runtimes.runc.options]
|
||||||
|
SystemdCgroup = true
|
||||||
|
`
|
||||||
|
testMergeConfig(t, []string{runcRuntime, nvidiaRuntime}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
|
||||||
|
// Merging a third config that customizes only the default_runtime_name should result in mostly identical result
|
||||||
|
runcDefault := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd]
|
||||||
|
default_runtime_name = "runc"
|
||||||
|
`
|
||||||
|
// This will then be the only difference in our expected TOML
|
||||||
|
expected2 := strings.Replace(expected, "default_runtime_name = 'nvidia'", "default_runtime_name = 'runc'", 1)
|
||||||
|
|
||||||
|
testMergeConfig(t, []string{runcRuntime, nvidiaRuntime, runcDefault}, expected2, "io.containerd.grpc.v1.cri")
|
||||||
|
|
||||||
|
// Mixing up the order will again result in 'nvidia' being the default runtime
|
||||||
|
testMergeConfig(t, []string{runcRuntime, runcDefault, nvidiaRuntime}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergingPluginsWithTwoCriRuntimeWithPodAnnotationsDropInConfigs(t *testing.T) {
|
||||||
|
runc1 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||||
|
runtime_type = "io.containerd.runc.v2"
|
||||||
|
cni_conf_dir = "/foo"
|
||||||
|
pod_annotations = ["a", "b", "c"]
|
||||||
|
`
|
||||||
|
runc2 := `
|
||||||
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||||
|
runtime_type = "io.containerd.runc.v2"
|
||||||
|
cni_conf_dir = "/bar"
|
||||||
|
pod_annotations = ["d", "e", "f"]
|
||||||
|
`
|
||||||
|
expected := `
|
||||||
|
[containerd]
|
||||||
|
[containerd.runtimes]
|
||||||
|
[containerd.runtimes.runc]
|
||||||
|
cni_conf_dir = '/bar'
|
||||||
|
pod_annotations = ['d', 'e', 'f']
|
||||||
|
runtime_type = 'io.containerd.runc.v2'
|
||||||
|
`
|
||||||
|
testMergeConfig(t, []string{runc1, runc2}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
|
||||||
|
// The other way around: runc1 over runc2
|
||||||
|
expected = `
|
||||||
|
[containerd]
|
||||||
|
[containerd.runtimes]
|
||||||
|
[containerd.runtimes.runc]
|
||||||
|
cni_conf_dir = '/foo'
|
||||||
|
pod_annotations = ['a', 'b', 'c']
|
||||||
|
runtime_type = 'io.containerd.runc.v2'
|
||||||
|
`
|
||||||
|
testMergeConfig(t, []string{runc2, runc1}, expected, "io.containerd.grpc.v1.cri")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMergeConfig(t *testing.T, inputs []string, expected string, comparePlugin string) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
var result Config
|
||||||
|
|
||||||
|
for i, data := range inputs {
|
||||||
|
filename := fmt.Sprintf("data%d.toml", i+1)
|
||||||
|
filepath := filepath.Join(tempDir, filename)
|
||||||
|
err := os.WriteFile(filepath, []byte(data), 0600)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
var tempOut Config
|
||||||
|
err = LoadConfig(context.Background(), filepath, &tempOut)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
result = tempOut
|
||||||
|
} else {
|
||||||
|
err = mergeConfig(&result, &tempOut)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criPlugin := result.Plugins[comparePlugin]
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := toml.NewEncoder(&buf).SetIndentTables(true).Encode(criPlugin); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, strings.TrimLeft(expected, "\n"), buf.String())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user