config_v1.go 5.79 KB
Newer Older
songlinfeng's avatar
songlinfeng committed
1
2
3
4
5
6
7
/**
# Copyright (c) 2024, HCUOpt CORPORATION.  All rights reserved.
**/

package containerd

import (
8
	"dcu-container-toolkit/pkg/config/engine"
songlinfeng's avatar
songlinfeng committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
	"fmt"

	"github.com/pelletier/go-toml"
)

// ConfigV1 represents a version 1 containerd config
type ConfigV1 Config

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

// AddRuntime adds a runtime to the containerd config
func (c *ConfigV1) AddRuntime(name string, path string, setAsDefault bool, configOverrides ...map[string]interface{}) error {
	if c == nil || c.Tree == nil {
		return fmt.Errorf("config is nil")
	}

	config := *c.Tree

	config.Set("version", int64(1))

	if runc, ok := config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", "runc"}).(*toml.Tree); ok {
		runc, _ = toml.Load(runc.String())
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name}, runc)
	}

	if config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", name}) == nil {
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "runtime_type"}, c.RuntimeType)
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "runtime_root"}, "")
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "runtime_engine"}, "")
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "privileged_without_host_devices"}, false)
	}

	if len(c.ContainerAnnotations) > 0 {
		annotations, err := (*Config)(c).getRuntimeAnnotations([]string{"plugins", "cri", "containerd", "runtimes", name, "container_annotations"})
		if err != nil {
			return err
		}
		annotations = append(c.ContainerAnnotations, annotations...)
		config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "container_annotations"}, annotations)
	}

	config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "BinaryName"}, path)
	config.SetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "Runtime"}, path)

	if setAsDefault && c.UseDefaultRuntimeName {
		config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"}, name)
	} else if setAsDefault {
		// Note: This is deprecated in containerd 1.4.0 and will be removed in 1.5.0
		if config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime"}) == nil {
			config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_type"}, c.RuntimeType)
			config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_root"}, "")
			config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "runtime_engine"}, "")
			config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "privileged_without_host_devices"}, false)
		}
		config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "BinaryName"}, path)
		config.SetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "Runtime"}, path)

		defaultRuntimeSubtree := subtreeAtPath(config, "plugins", "cri", "containerd", "default_runtime")
		if err := defaultRuntimeSubtree.applyOverrides(configOverrides...); err != nil {
			return fmt.Errorf("failed to apply config overrides to default_runtime: %w", err)
		}
	}

	runtimeSubtree := subtreeAtPath(config, "plugins", "cri", "containerd", "runtimes", name)
	if err := runtimeSubtree.applyOverrides(configOverrides...); err != nil {
		return fmt.Errorf("failed to apply config overrides: %w", err)
	}

	*c.Tree = config
	return nil
}

// DefaultRuntime returns the default runtime for the cri-o config
func (c ConfigV1) DefaultRuntime() string {
	if runtime, ok := c.GetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"}).(string); ok {
		return runtime
	}
	return ""
}

// RemoveRuntime removes a runtime from the docker config
func (c *ConfigV1) RemoveRuntime(name string) error {
	if c == nil || c.Tree == nil {
		return nil
	}

	config := *c.Tree

	// If the specified runtime was set as the default runtime we need to remove the default runtime too.
	runtimePath, ok := config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "BinaryName"}).(string)
	if !ok || runtimePath == "" {
		runtimePath, _ = config.GetPath([]string{"plugins", "cri", "containerd", "runtimes", name, "options", "Runtime"}).(string)
	}
	defaultRuntimePath, ok := config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "BinaryName"}).(string)
	if !ok || defaultRuntimePath == "" {
		defaultRuntimePath, _ = config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime", "options", "Runtime"}).(string)
	}
	if runtimePath != "" && defaultRuntimePath != "" && runtimePath == defaultRuntimePath {
		config.DeletePath([]string{"plugins", "cri", "containerd", "default_runtime"})
	}

	config.DeletePath([]string{"plugins", "cri", "containerd", "runtimes", name})
	if runtime, ok := config.GetPath([]string{"plugins", "cri", "containerd", "default_runtime_name"}).(string); ok {
		if runtime == name {
			config.DeletePath([]string{"plugins", "cri", "containerd", "default_runtime_name"})
		}
	}

	runtimeConfigPath := []string{"plugins", "cri", "containerd", "runtimes", name}
	for i := 0; i < len(runtimeConfigPath); i++ {
		if runtimes, ok := config.GetPath(runtimeConfigPath[:len(runtimeConfigPath)-i]).(*toml.Tree); ok {
			if len(runtimes.Keys()) == 0 {
				config.DeletePath(runtimeConfigPath[:len(runtimeConfigPath)-i])
			}
		}
	}

	if len(config.Keys()) == 1 && config.Keys()[0] == "version" {
		config.Delete("version")
	}

	*c.Tree = config
	return nil
}

// SetOption sets the specified containerd option.
func (c *ConfigV1) Set(key string, value interface{}) {
	config := *c.Tree
	config.SetPath([]string{"plugins", "cri", "containerd", key}, value)
	*c.Tree = config
}

// Save wrotes the config to a file
func (c ConfigV1) Save(path string) (int64, error) {
	return (Config)(c).Save(path)
}