diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index f624e4da89..e55fb71c06 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -569,7 +569,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N nodeConfig.Containerd.Debug = envInfo.Debug applyContainerdStateAndAddress(nodeConfig) applyCRIDockerdAddress(nodeConfig) - applyContainerdQoSClassConfigFileIfPresent(envInfo, nodeConfig) + applyContainerdQoSClassConfigFileIfPresent(envInfo, &nodeConfig.Containerd) nodeConfig.Containerd.Template = filepath.Join(envInfo.DataDir, "agent", "etc", "containerd", "config.toml.tmpl") nodeConfig.Certificate = servingCert diff --git a/pkg/agent/config/config_linux.go b/pkg/agent/config/config_linux.go index c29e0a7d8b..b668ab0a68 100644 --- a/pkg/agent/config/config_linux.go +++ b/pkg/agent/config/config_linux.go @@ -22,20 +22,26 @@ func applyCRIDockerdAddress(nodeConfig *config.Node) { nodeConfig.CRIDockerd.Address = "unix:///run/k3s/cri-dockerd/cri-dockerd.sock" } -func applyContainerdQoSClassConfigFileIfPresent(envInfo *cmds.Agent, nodeConfig *config.Node) { - blockioPath := filepath.Join(envInfo.DataDir, "agent", "etc", "containerd", "blockio_config.yaml") +func applyContainerdQoSClassConfigFileIfPresent(envInfo *cmds.Agent, containerdConfig *config.Containerd) { + containerdConfigDir := filepath.Join(envInfo.DataDir, "agent", "etc", "containerd") + + blockioPath := filepath.Join(containerdConfigDir, "blockio_config.yaml") // Set containerd config if file exists - if _, err := os.Stat(blockioPath); !errors.Is(err, os.ErrNotExist) { - logrus.Infof("BlockIO configuration file found") - nodeConfig.Containerd.BlockIOConfig = blockioPath + if fileInfo, err := os.Stat(blockioPath); !errors.Is(err, os.ErrNotExist) { + if fileInfo.Mode().IsRegular() { + logrus.Infof("BlockIO configuration file found") + containerdConfig.BlockIOConfig = blockioPath + } } - rdtPath := filepath.Join(envInfo.DataDir, "agent", "etc", "containerd", "rdt_config.yaml") + rdtPath := filepath.Join(containerdConfigDir, "rdt_config.yaml") // Set containerd config if file exists - if _, err := os.Stat(rdtPath); !errors.Is(err, os.ErrNotExist) { - logrus.Infof("RDT configuration file found") - nodeConfig.Containerd.RDTConfig = rdtPath + if fileInfo, err := os.Stat(rdtPath); !errors.Is(err, os.ErrNotExist) { + if fileInfo.Mode().IsRegular() { + logrus.Infof("RDT configuration file found") + containerdConfig.RDTConfig = rdtPath + } } } diff --git a/pkg/agent/config/config_linux_test.go b/pkg/agent/config/config_linux_test.go new file mode 100644 index 0000000000..868304fcb8 --- /dev/null +++ b/pkg/agent/config/config_linux_test.go @@ -0,0 +1,165 @@ +//go:build linux +// +build linux + +package config + +import ( + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/k3s-io/k3s/pkg/cli/cmds" + "github.com/k3s-io/k3s/pkg/daemons/config" + "github.com/k3s-io/k3s/tests" +) + +func Test_UnitApplyContainerdQoSClassConfigFileIfPresent(t *testing.T) { + configControl := config.Control{ + DataDir: "/tmp/k3s/", + } + + if err := tests.GenerateDataDir(&configControl); err != nil { + t.Errorf("Test_UnitApplyContainerdQoSClassConfigFileIfPresent() setup failed = %v", err) + } + defer tests.CleanupDataDir(&configControl) + + containerdConfigDir := filepath.Join(configControl.DataDir, "agent", "etc", "containerd") + os.MkdirAll(containerdConfigDir, 0700) + + type args struct { + envInfo *cmds.Agent + containerdConfig *config.Containerd + } + tests := []struct { + name string + args args + setup func() error + teardown func() + want *config.Containerd + }{ + { + name: "No config file", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + return nil + }, + teardown: func() {}, + want: &config.Containerd{}, + }, + { + name: "BlockIO config file", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + _, err := os.Create(filepath.Join(containerdConfigDir, "blockio_config.yaml")) + return err + }, + teardown: func() { + os.Remove(filepath.Join(containerdConfigDir, "blockio_config.yaml")) + }, + want: &config.Containerd{ + BlockIOConfig: filepath.Join(containerdConfigDir, "blockio_config.yaml"), + }, + }, + { + name: "RDT config file", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + _, err := os.Create(filepath.Join(containerdConfigDir, "rdt_config.yaml")) + return err + }, + teardown: func() { + os.Remove(filepath.Join(containerdConfigDir, "rdt_config.yaml")) + }, + want: &config.Containerd{ + RDTConfig: filepath.Join(containerdConfigDir, "rdt_config.yaml"), + }, + }, + { + name: "Both config files", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + _, err := os.Create(filepath.Join(containerdConfigDir, "blockio_config.yaml")) + if err != nil { + return err + } + _, err = os.Create(filepath.Join(containerdConfigDir, "rdt_config.yaml")) + return err + }, + teardown: func() { + os.Remove(filepath.Join(containerdConfigDir, "blockio_config.yaml")) + os.Remove(filepath.Join(containerdConfigDir, "rdt_config.yaml")) + }, + want: &config.Containerd{ + BlockIOConfig: filepath.Join(containerdConfigDir, "blockio_config.yaml"), + RDTConfig: filepath.Join(containerdConfigDir, "rdt_config.yaml"), + }, + }, + { + name: "BlockIO path is a directory", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + return os.Mkdir(filepath.Join(containerdConfigDir, "blockio_config.yaml"), 0700) + }, + teardown: func() { + os.Remove(filepath.Join(containerdConfigDir, "blockio_config.yaml")) + }, + want: &config.Containerd{}, + }, + { + name: "RDT path is a directory", + args: args{ + envInfo: &cmds.Agent{ + DataDir: configControl.DataDir, + }, + containerdConfig: &config.Containerd{}, + }, + setup: func() error { + return os.Mkdir(filepath.Join(containerdConfigDir, "rdt_config.yaml"), 0700) + }, + teardown: func() { + os.Remove(filepath.Join(containerdConfigDir, "rdt_config.yaml")) + }, + want: &config.Containerd{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + defer tt.teardown() + + envInfo := tt.args.envInfo + containerdConfig := tt.args.containerdConfig + applyContainerdQoSClassConfigFileIfPresent(envInfo, containerdConfig) + if !reflect.DeepEqual(containerdConfig, tt.want) { + t.Errorf("applyContainerdQoSClassConfigFileIfPresent() = %+v\nWant %+v", containerdConfig, tt.want) + } + }) + } +} diff --git a/pkg/agent/config/config_windows.go b/pkg/agent/config/config_windows.go index 351d624efb..226ea7a013 100644 --- a/pkg/agent/config/config_windows.go +++ b/pkg/agent/config/config_windows.go @@ -19,6 +19,6 @@ func applyCRIDockerdAddress(nodeConfig *config.Node) { nodeConfig.CRIDockerd.Address = "npipe:////.pipe/cri-dockerd" } -func applyContainerdQoSClassConfigFileIfPresent(envInfo *cmds.Agent, nodeConfig *config.Node) { +func applyContainerdQoSClassConfigFileIfPresent(envInfo *cmds.Agent, containerdConfig *config.Containerd) { // QoS-class resource management not supported on windows. }