Skip to content

Commit

Permalink
Merge pull request #4575 from twz123/marshal-containerd-toml
Browse files Browse the repository at this point in the history
Marshal containerd.toml instead of templating it
  • Loading branch information
twz123 authored Jun 11, 2024
2 parents fd93979 + 76d5ffe commit 50fb76c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 46 deletions.
54 changes: 23 additions & 31 deletions pkg/component/worker/containerd/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,16 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"syscall"
"time"

"github.com/BurntSushi/toml"
"github.com/fsnotify/fsnotify"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"

"github.com/k0sproject/k0s/internal/pkg/dir"
"github.com/k0sproject/k0s/internal/pkg/file"
"github.com/k0sproject/k0s/internal/pkg/templatewriter"
"github.com/k0sproject/k0s/pkg/assets"
"github.com/k0sproject/k0s/pkg/component/manager"
workerconfig "github.com/k0sproject/k0s/pkg/component/worker/config"
Expand All @@ -48,16 +47,10 @@ import (
"github.com/k0sproject/k0s/pkg/supervisor"
)

const confTmpl = `# k0s_managed=true
const containerdTomlHeader = `# k0s_managed=true
# This is a placeholder configuration for k0s managed containerd.
# If you wish to override the config, remove the first line and replace this file with your custom configuration.
# For reference see https://github.com/containerd/containerd/blob/main/docs/man/containerd-config.toml.5.md
version = 2
imports = [
{{- range $i := .Imports }}
"{{ $i }}",
{{- end }}
]
`
const confPathPosix = "/etc/k0s/containerd.toml"
const confPathWindows = "C:\\Program Files\\containerd\\config.toml"
Expand Down Expand Up @@ -210,33 +203,32 @@ func (c *Component) setupConfig() error {
}

criConfigPath := filepath.Join(c.K0sVars.RunDir, "containerd-cri.toml")
err = file.WriteContentAtomically(criConfigPath, []byte(config.CRIConfig), 0644)
if err != nil {
return fmt.Errorf("can't create containerd CRI config: %w", err)
}

var data struct{ Imports []string }
data.Imports = append(config.ImportPaths, criConfigPath)

// double escape for windows because containerd expects
// double backslash in the configuration but golang templates
// unescape double slash to a single slash
if runtime.GOOS == "windows" {
for i := range data.Imports {
data.Imports[i] = strings.ReplaceAll(data.Imports[i], "\\", "\\\\")
}
if err = file.AtomicWithTarget(criConfigPath).
WithPermissions(0644).
WriteString(config.CRIConfig); err != nil {
return fmt.Errorf("can't create containerd CRI config: %w", err)
}

output := bytes.NewBuffer([]byte{})
tw := templatewriter.TemplateWriter{
Name: "containerdconfig",
Template: confTmpl,
Data: data,
}
if err := tw.WriteToBuffer(output); err != nil {
if err := file.AtomicWithTarget(c.confPath).
WithPermissions(0644).
Do(func(f file.AtomicWriter) error {
w := bufio.NewWriter(f)
if _, err := w.WriteString(containerdTomlHeader); err != nil {
return err
}
if err := toml.NewEncoder(w).Encode(map[string]any{
"version": 2,
"imports": append(config.ImportPaths, criConfigPath),
}); err != nil {
return err
}
return w.Flush()
}); err != nil {
return fmt.Errorf("can't create containerd config: %w", err)
}
return file.WriteContentAtomically(c.confPath, output.Bytes(), 0644)

return nil
}

func (c *Component) watchDropinConfigs(ctx context.Context) {
Expand Down
21 changes: 9 additions & 12 deletions pkg/component/worker/containerd/configurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,18 @@ func generateDefaultCRIConfig(sandboxContainerImage string) ([]byte, error) {
// Set pause image
criPluginConfig.SandboxImage = sandboxContainerImage
if runtime.GOOS == "windows" {
criPluginConfig.CniConfig.NetworkPluginBinDir = "c:\\opt\\cni\\bin"
criPluginConfig.CniConfig.NetworkPluginConfDir = "c:\\opt\\cni\\conf"
// The default config for Windows uses %ProgramFiles%/containerd/cni/{bin,conf}.
// Maybe k0s can use the default in the future, so there's no need for this override.
criPluginConfig.CniConfig.NetworkPluginBinDir = `c:\opt\cni\bin`
criPluginConfig.CniConfig.NetworkPluginConfDir = `c:\opt\cni\conf`
}
// We need to use custom struct so we can unmarshal the CRI plugin config only
containerdConfig := struct {
Version int `toml:"version"`
Plugins map[string]interface{} `toml:"plugins"`
}{
Version: 2,
Plugins: map[string]interface{}{

return toml.Marshal(map[string]any{
"version": 2,
"plugins": map[string]any{
"io.containerd.grpc.v1.cri": criPluginConfig,
},
}

return toml.Marshal(containerdConfig)
})
}

func hasCRIPluginConfig(data []byte) (bool, error) {
Expand Down
9 changes: 6 additions & 3 deletions pkg/component/worker/containerd/configurer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ func TestConfigurer_HandleImports(t *testing.T) {
err := os.WriteFile(filepath.Join(importsPath, "foo.toml"), []byte(criRuntimeConfig), 0644)
require.NoError(t, err)
c := configurer{
loadPath: filepath.Join(importsPath, "*.toml"),
log: logrus.New().WithField("test", t.Name()),
loadPath: filepath.Join(importsPath, "*.toml"),
pauseImage: "pause:42",
log: logrus.New().WithField("test", t.Name()),
}
criConfig, err := c.handleImports()
assert.NoError(t, err)
Expand All @@ -60,8 +61,10 @@ func TestConfigurer_HandleImports(t *testing.T) {
assert.Equal(t, 2, containerdConfig.Version)
criPluginConfig := containerdConfig.Plugins["io.containerd.grpc.v1.cri"]
require.NotNil(t, criPluginConfig, "No CRI plugin configuration section found")
sandboxImage := criPluginConfig.Get("sandbox_image")
assert.Equal(t, "pause:42", sandboxImage, "Custom pause image not found in CRI configuration")
snapshotter := criPluginConfig.GetPath([]string{"containerd", "snapshotter"})
require.Equal(t, "zfs", snapshotter)
assert.Equal(t, "zfs", snapshotter, "Overridden snapshotter not found in CRI configuration")
})

t.Run("should have no imports if imports dir is empty", func(t *testing.T) {
Expand Down

0 comments on commit 50fb76c

Please sign in to comment.