/** # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. */ package main import ( "fmt" "testing" "github.com/NVIDIA/nvidia-container-toolkit/internal/config/engine/containerd" "github.com/pelletier/go-toml" "github.com/stretchr/testify/require" ) const ( runtimeType = "runtime_type" ) func TestUpdateV2ConfigDefaultRuntime(t *testing.T) { const runtimeDir = "/test/runtime/dir" testCases := []struct { setAsDefault bool runtimeClass string expectedDefaultRuntimeName interface{} }{ {}, { setAsDefault: false, runtimeClass: "nvidia", expectedDefaultRuntimeName: nil, }, { setAsDefault: false, runtimeClass: "NAME", expectedDefaultRuntimeName: nil, }, { setAsDefault: false, runtimeClass: "nvidia-experimental", expectedDefaultRuntimeName: nil, }, { setAsDefault: true, runtimeClass: "nvidia", expectedDefaultRuntimeName: "nvidia", }, { setAsDefault: true, runtimeClass: "NAME", expectedDefaultRuntimeName: "NAME", }, { setAsDefault: true, runtimeClass: "nvidia-experimental", expectedDefaultRuntimeName: "nvidia-experimental", }, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { o := &options{ setAsDefault: tc.setAsDefault, runtimeClass: tc.runtimeClass, runtimeDir: runtimeDir, } config, err := toml.TreeFromMap(map[string]interface{}{}) require.NoError(t, err) v2 := &containerd.Config{ Tree: config, RuntimeType: runtimeType, } err = UpdateConfig(v2, o) require.NoError(t, err) defaultRuntimeName := config.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"}) require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName) }) } } func TestUpdateV2Config(t *testing.T) { const runtimeDir = "/test/runtime/dir" const expectedVersion = int64(2) testCases := []struct { runtimeClass string expectedConfig map[string]interface{} }{ { runtimeClass: "nvidia", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "nvidia": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, { runtimeClass: "NAME", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "NAME": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, { runtimeClass: "nvidia-experimental", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "nvidia": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runtime_type", "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { o := &options{ runtimeClass: tc.runtimeClass, runtimeType: runtimeType, runtimeDir: runtimeDir, } config, err := toml.TreeFromMap(map[string]interface{}{}) require.NoError(t, err) v2 := &containerd.Config{ Tree: config, RuntimeType: runtimeType, ContainerAnnotations: []string{"cdi.k8s.io/*"}, } err = UpdateConfig(v2, o) require.NoError(t, err) expected, err := toml.TreeFromMap(tc.expectedConfig) require.NoError(t, err) require.Equal(t, expected.String(), config.String()) }) } } func TestUpdateV2ConfigWithRuncPresent(t *testing.T) { const runtimeDir = "/test/runtime/dir" testCases := []struct { runtimeClass string expectedConfig map[string]interface{} }{ { runtimeClass: "nvidia", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "runc": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/runc-binary", }, }, "nvidia": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, { runtimeClass: "NAME", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "runc": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/runc-binary", }, }, "NAME": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, { runtimeClass: "nvidia-experimental", expectedConfig: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "runc": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/runc-binary", }, }, "nvidia": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime", }, }, "nvidia-experimental": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.experimental", }, }, "nvidia-cdi": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.cdi", }, }, "nvidia-legacy": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "container_annotations": []string{"cdi.k8s.io/*"}, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": "/test/runtime/dir/nvidia-container-runtime.legacy", }, }, }, }, }, }, }, }, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { o := &options{ runtimeClass: tc.runtimeClass, runtimeType: runtimeType, runtimeDir: runtimeDir, } config, err := toml.TreeFromMap(runcConfigMapV2("/runc-binary")) require.NoError(t, err) v2 := &containerd.Config{ Tree: config, RuntimeType: runtimeType, ContainerAnnotations: []string{"cdi.k8s.io/*"}, } err = UpdateConfig(v2, o) require.NoError(t, err) expected, err := toml.TreeFromMap(tc.expectedConfig) require.NoError(t, err) require.Equal(t, expected.String(), config.String()) }) } } func TestRevertV2Config(t *testing.T) { testCases := []struct { config map[string]interface { } expected map[string]interface{} }{ {}, { config: map[string]interface{}{ "version": int64(2), }, }, { config: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "nvidia": runtimeMapV2("/test/runtime/dir/nvidia-container-runtime"), "nvidia-experimental": runtimeMapV2("/test/runtime/dir/nvidia-container-runtime.experimental"), }, }, }, }, }, }, { config: map[string]interface{}{ "version": int64(2), "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "nvidia": runtimeMapV2("/test/runtime/dir/nvidia-container-runtime"), "nvidia-experimental": runtimeMapV2("/test/runtime/dir/nvidia-container-runtime.experimental"), }, "default_runtime_name": "nvidia", }, }, }, }, }, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { o := &options{ runtimeClass: "nvidia", } config, err := toml.TreeFromMap(tc.config) require.NoError(t, err) expected, err := toml.TreeFromMap(tc.expected) require.NoError(t, err) v2 := &containerd.Config{ Tree: config, RuntimeType: runtimeType, } err = RevertConfig(v2, o) require.NoError(t, err) configContents, _ := toml.Marshal(config) expectedContents, _ := toml.Marshal(expected) require.Equal(t, string(expectedContents), string(configContents)) }) } } func runtimeMapV2(binary string) map[string]interface{} { return map[string]interface{}{ "runtime_type": runtimeType, "runtime_root": "", "runtime_engine": "", "privileged_without_host_devices": false, "options": map[string]interface{}{ "BinaryName": binary, }, } } func runcConfigMapV2(binary string) map[string]interface{} { return map[string]interface{}{ "plugins": map[string]interface{}{ "io.containerd.grpc.v1.cri": map[string]interface{}{ "containerd": map[string]interface{}{ "runtimes": map[string]interface{}{ "runc": map[string]interface{}{ "runtime_type": "runc_runtime_type", "runtime_root": "runc_runtime_root", "runtime_engine": "runc_runtime_engine", "privileged_without_host_devices": true, "options": map[string]interface{}{ "runc-option": "value", "BinaryName": binary, }, }, }, }, }, }, } }