*
* Copyright (c) 2025 Bocloud Technologies Co., Ltd.
* installer is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* <http://license.coscl.org.cn/MulanPSL2>
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*
*/
package infrastructure
import (
"context"
"fmt"
"net"
"testing"
"time"
"github.com/agiledragon/gomonkey/v2"
containerd_v2 "github.com/containerd/containerd/v2/client"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/stretchr/testify/assert"
"gopkg.openfuyao.cn/bkeadm/pkg/executor/containerd"
"gopkg.openfuyao.cn/bkeadm/pkg/executor/docker"
"gopkg.openfuyao.cn/bkeadm/pkg/global"
cond "gopkg.openfuyao.cn/bkeadm/pkg/infrastructure/containerd"
"gopkg.openfuyao.cn/bkeadm/pkg/infrastructure/dockerd"
"gopkg.openfuyao.cn/bkeadm/pkg/infrastructure/k3s"
"gopkg.openfuyao.cn/bkeadm/utils"
"gopkg.openfuyao.cn/bkeadm/utils/log"
)
const (
testIPv4SegmentA = 192
testIPv4SegmentB = 168
testIPv4SegmentC = 1
testIPv4SegmentD = 100
testKubernetesPortValue = 6443
)
var testHostIP = net.IPv4(
testIPv4SegmentA,
testIPv4SegmentB,
testIPv4SegmentC,
testIPv4SegmentD,
).String()
var testKubernetesPort = fmt.Sprintf("%d", testKubernetesPortValue)
func TestRuntimeConfigStruct(t *testing.T) {
cfg := &RuntimeConfig{}
cfg.Runtime = "docker"
cfg.RuntimeStorage = "/var/lib/docker"
cfg.Domain = "registry.example.com"
cfg.ContainerdFile = "/path/to/containerd.tar.gz"
cfg.CniPluginFile = "/path/to/cni.tar.gz"
cfg.DockerdFile = "/path/to/dockerd.tar.gz"
cfg.HostIP = testHostIP
cfg.CAFile = "/path/to/ca.crt"
assert.Equal(t, "docker", cfg.Runtime)
assert.Equal(t, "/var/lib/docker", cfg.RuntimeStorage)
assert.Equal(t, "registry.example.com", cfg.Domain)
assert.Equal(t, "/path/to/containerd.tar.gz", cfg.ContainerdFile)
assert.Equal(t, "/path/to/cni.tar.gz", cfg.CniPluginFile)
assert.Equal(t, "/path/to/dockerd.tar.gz", cfg.DockerdFile)
assert.Equal(t, testHostIP, cfg.HostIP)
assert.Equal(t, "/path/to/ca.crt", cfg.CAFile)
}
func TestIsDocker(t *testing.T) {
tests := []struct {
name string
mockNewDockerClient func() (docker.DockerClient, error)
mockGetClient func() *client.Client
mockPing func(*client.Client, context.Context) (types.Ping, error)
globalDocker docker.DockerClient
expectedResult bool
}{
{
name: "docker client is ready",
mockNewDockerClient: func() (docker.DockerClient, error) {
return &docker.Client{Client: &client.Client{}}, nil
},
mockGetClient: func() *client.Client {
return &client.Client{}
},
mockPing: func(c *client.Client, ctx context.Context) (types.Ping, error) {
return types.Ping{}, nil
},
globalDocker: nil,
expectedResult: true,
},
{
name: "global docker client already exists and is ready",
mockGetClient: func() *client.Client {
return &client.Client{}
},
mockPing: func(c *client.Client, ctx context.Context) (types.Ping, error) {
return types.Ping{}, nil
},
globalDocker: &docker.Client{Client: &client.Client{}},
expectedResult: true,
},
{
name: "docker client ping fails",
mockNewDockerClient: func() (docker.DockerClient, error) {
return &docker.Client{Client: &client.Client{}}, nil
},
mockGetClient: func() *client.Client {
return &client.Client{}
},
mockPing: func(c *client.Client, ctx context.Context) (types.Ping, error) {
return types.Ping{}, fmt.Errorf("ping failed")
},
globalDocker: nil,
expectedResult: false,
},
{
name: "docker client creation fails",
mockNewDockerClient: func() (docker.DockerClient, error) {
return nil, fmt.Errorf("client creation failed")
},
globalDocker: nil,
expectedResult: false,
},
{
name: "global docker is nil and new client creation returns nil",
mockNewDockerClient: func() (docker.DockerClient, error) {
return nil, nil
},
globalDocker: nil,
expectedResult: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
originalDocker := global.Docker
global.Docker = tt.globalDocker
defer func() {
global.Docker = originalDocker
}()
if tt.globalDocker == nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(docker.NewDockerClient, tt.mockNewDockerClient)
}
if tt.mockGetClient != nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc((*docker.Client).GetClient, tt.mockGetClient)
}
if tt.mockPing != nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc((*client.Client).Ping, tt.mockPing)
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(log.Info, func(v ...interface{}) {})
result := IsDocker()
assert.Equal(t, tt.expectedResult, result)
})
}
}
func TestIsContainerd(t *testing.T) {
tests := []struct {
name string
mockNewContainerdClient func() (containerd.ContainerdClient, error)
mockGetClient func() *containerd_v2.Client
mockIsServing func(*containerd_v2.Client, context.Context) (bool, error)
mockExists func(string) bool
globalContainerd containerd.ContainerdClient
expectedResult bool
}{
{
name: "containerd client is serving and nerdctl exists",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return &containerd.Client{}, nil
},
mockGetClient: func() *containerd_v2.Client {
return &containerd_v2.Client{}
},
mockIsServing: func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
return true, nil
},
mockExists: func(path string) bool {
return path == utils.NerdCtl
},
globalContainerd: nil,
expectedResult: true,
},
{
name: "global containerd client already exists and is serving",
mockGetClient: func() *containerd_v2.Client {
return &containerd_v2.Client{}
},
mockIsServing: func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
return true, nil
},
mockExists: func(path string) bool {
return path == utils.NerdCtl
},
globalContainerd: &containerd.Client{},
expectedResult: true,
},
{
name: "containerd client is serving but nerdctl doesn't exist",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return &containerd.Client{}, nil
},
mockGetClient: func() *containerd_v2.Client {
return &containerd_v2.Client{}
},
mockIsServing: func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
return true, nil
},
mockExists: func(path string) bool {
return path != utils.NerdCtl
},
globalContainerd: nil,
expectedResult: false,
},
{
name: "containerd client is not serving",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return &containerd.Client{}, nil
},
mockGetClient: func() *containerd_v2.Client {
return &containerd_v2.Client{}
},
mockIsServing: func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
return false, nil
},
globalContainerd: nil,
expectedResult: false,
},
{
name: "containerd client serving returns error",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return &containerd.Client{}, nil
},
mockGetClient: func() *containerd_v2.Client {
return &containerd_v2.Client{}
},
mockIsServing: func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
return false, fmt.Errorf("serving error")
},
globalContainerd: nil,
expectedResult: false,
},
{
name: "containerd client creation fails",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return nil, fmt.Errorf("client creation failed")
},
globalContainerd: nil,
expectedResult: false,
},
{
name: "global containerd is nil and new client creation returns nil",
mockNewContainerdClient: func() (containerd.ContainerdClient, error) {
return nil, nil
},
globalContainerd: nil,
expectedResult: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
originalContainerd := global.Containerd
global.Containerd = tt.globalContainerd
defer func() {
global.Containerd = originalContainerd
}()
if tt.globalContainerd == nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(containerd.NewContainedClient, tt.mockNewContainerdClient)
}
if tt.mockGetClient != nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc((*containerd.Client).GetClient, tt.mockGetClient)
}
if tt.mockIsServing != nil {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc((*containerd_v2.Client).IsServing, tt.mockIsServing)
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.Exists, tt.mockExists)
patches.ApplyFunc(log.Debug, func(v ...interface{}) {})
result := IsContainerd()
assert.Equal(t, tt.expectedResult, result)
})
}
}
func TestRuntimeInstall(t *testing.T) {
tests := []struct {
name string
cfg RuntimeConfig
mockIsDocker func() bool
mockIsContainerd func() bool
mockEnsureDockerServer func(string, string, string, string) error
mockInstall func(string, string, string, string) error
mockCniPluginInstall func(string) error
expectError bool
}{
{
name: "runtime already installed",
cfg: RuntimeConfig{Runtime: "docker"},
mockIsDocker: func() bool { return true },
mockIsContainerd: func() bool { return false },
expectError: false,
},
{
name: "both docker and containerd already installed",
cfg: RuntimeConfig{Runtime: "docker"},
mockIsDocker: func() bool { return true },
mockIsContainerd: func() bool { return true },
expectError: false,
},
{
name: "install docker runtime",
cfg: RuntimeConfig{
Runtime: "docker",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/docker",
DockerdFile: "/path/to/dockerd.tar.gz",
HostIP: testHostIP,
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockEnsureDockerServer: func(domain, storage, dockerFile, hostIP string) error {
return nil
},
expectError: false,
},
{
name: "install containerd runtime",
cfg: RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockInstall: func(domain, storage, containerdFile, caFile string) error {
return nil
},
expectError: false,
},
{
name: "install containerd with cni plugin",
cfg: RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
CniPluginFile: "/path/to/cni.tar.gz",
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockInstall: func(domain, storage, containerdFile, caFile string) error {
return nil
},
mockCniPluginInstall: func(cniPluginFile string) error {
return nil
},
expectError: false,
},
{
name: "docker installation fails",
cfg: RuntimeConfig{
Runtime: "docker",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/docker",
DockerdFile: "/path/to/dockerd.tar.gz",
HostIP: testHostIP,
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockEnsureDockerServer: func(domain, storage, dockerFile, hostIP string) error {
return fmt.Errorf("docker install failed")
},
expectError: true,
},
{
name: "containerd installation fails",
cfg: RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockInstall: func(domain, storage, containerdFile, caFile string) error {
return fmt.Errorf("containerd install failed")
},
expectError: true,
},
{
name: "cni plugin installation fails",
cfg: RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
CniPluginFile: "/path/to/cni.tar.gz",
},
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
mockInstall: func(domain, storage, containerdFile, caFile string) error {
return nil
},
mockCniPluginInstall: func(cniPluginFile string) error {
return fmt.Errorf("cni install failed")
},
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, tt.mockIsDocker)
patches.ApplyFunc(IsContainerd, tt.mockIsContainerd)
if !tt.mockIsDocker() && !tt.mockIsContainerd() {
if tt.cfg.Runtime == "docker" {
patches.ApplyFunc(dockerd.EnsureDockerServer, tt.mockEnsureDockerServer)
} else if tt.cfg.Runtime == "containerd" {
patches.ApplyFunc(cond.Install, tt.mockInstall)
if tt.cfg.CniPluginFile != "" {
patches.ApplyFunc(cond.CniPluginInstall, tt.mockCniPluginInstall)
}
}
}
err := RuntimeInstall(tt.cfg)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestStartLocalKubernetes(t *testing.T) {
cfg := k3s.Config{
HostIP: testHostIP,
KubernetesPort: testKubernetesPort,
}
localImage := "test-image:latest"
tests := []struct {
name string
mockIsDocker func() bool
mockIsContainerd func() bool
mockStartK3sWithDocker func(k3s.Config, string) error
mockEnsureDirExists func(string) error
mockStartK3sWithContainerd func(k3s.Config, string) error
expectError bool
}{
{
name: "start with docker",
mockIsDocker: func() bool { return true },
mockIsContainerd: func() bool { return false },
mockStartK3sWithDocker: func(c k3s.Config, image string) error {
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
},
expectError: false,
},
{
name: "start with containerd",
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return true },
mockEnsureDirExists: func(dir string) error {
assert.Equal(t, utils.DefaultExtendManifestsDir, dir)
return nil
},
mockStartK3sWithContainerd: func(c k3s.Config, image string) error {
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
},
expectError: false,
},
{
name: "start with both docker and containerd",
mockIsDocker: func() bool { return true },
mockIsContainerd: func() bool { return true },
mockStartK3sWithDocker: func(c k3s.Config, image string) error {
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
},
mockEnsureDirExists: func(dir string) error {
assert.Equal(t, utils.DefaultExtendManifestsDir, dir)
return nil
},
mockStartK3sWithContainerd: func(c k3s.Config, image string) error {
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
},
expectError: false,
},
{
name: "start with docker fails",
mockIsDocker: func() bool { return true },
mockIsContainerd: func() bool { return false },
mockStartK3sWithDocker: func(c k3s.Config, image string) error {
return fmt.Errorf("k3s docker failed")
},
expectError: true,
},
{
name: "ensure dir fails",
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return true },
mockEnsureDirExists: func(dir string) error {
return fmt.Errorf("ensure dir failed")
},
expectError: true,
},
{
name: "start with containerd fails",
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return true },
mockEnsureDirExists: func(dir string) error {
return nil
},
mockStartK3sWithContainerd: func(c k3s.Config, image string) error {
return fmt.Errorf("k3s containerd failed")
},
expectError: true,
},
{
name: "neither docker nor containerd available",
mockIsDocker: func() bool { return false },
mockIsContainerd: func() bool { return false },
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, tt.mockIsDocker)
patches.ApplyFunc(IsContainerd, tt.mockIsContainerd)
if tt.mockIsDocker() {
patches.ApplyFunc(k3s.StartK3sWithDocker, tt.mockStartK3sWithDocker)
}
if tt.mockIsContainerd() {
if tt.mockEnsureDirExists != nil {
patches.ApplyFunc(k3s.EnsureDirExists, tt.mockEnsureDirExists)
}
patches.ApplyFunc(k3s.StartK3sWithContainerd, tt.mockStartK3sWithContainerd)
}
err := StartLocalKubernetes(cfg, localImage)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestIsDockerWithTimeout(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(docker.NewDockerClient, func() (docker.DockerClient, error) {
return &docker.Client{Client: &client.Client{}}, nil
})
patches.ApplyFunc((*docker.Client).GetClient, func(c *docker.Client) *client.Client {
return &client.Client{}
})
var capturedCtx context.Context
patches.ApplyFunc((*client.Client).Ping, func(c *client.Client, ctx context.Context) (types.Ping, error) {
capturedCtx = ctx
return types.Ping{}, nil
})
patches.ApplyFunc(log.Info, func(v ...interface{}) {})
originalDocker := global.Docker
global.Docker = nil
defer func() {
global.Docker = originalDocker
}()
result := IsDocker()
assert.True(t, result)
assert.NotNil(t, capturedCtx)
deadline, ok := capturedCtx.Deadline()
assert.True(t, ok)
expectedDeadline := time.Now().Add(utils.DefaultTimeoutSeconds * time.Second)
assert.WithinDuration(t, expectedDeadline, deadline, time.Second)
}
func TestIsContainerdWithTimeout(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(containerd.NewContainedClient, func() (containerd.ContainerdClient, error) {
return &containerd.Client{}, nil
})
patches.ApplyFunc((*containerd.Client).GetClient, func(c *containerd.Client) *containerd_v2.Client {
return &containerd_v2.Client{}
})
var capturedCtx context.Context
patches.ApplyFunc((*containerd_v2.Client).IsServing, func(c *containerd_v2.Client, ctx context.Context) (bool, error) {
capturedCtx = ctx
return true, nil
})
patches.ApplyFunc(utils.Exists, func(path string) bool {
return path == utils.NerdCtl
})
patches.ApplyFunc(log.Debug, func(v ...interface{}) {})
originalContainerd := global.Containerd
global.Containerd = nil
defer func() {
global.Containerd = originalContainerd
}()
result := IsContainerd()
assert.True(t, result)
assert.NotNil(t, capturedCtx)
deadline, ok := capturedCtx.Deadline()
assert.True(t, ok)
expectedDeadline := time.Now().Add(utils.DefaultTimeoutSeconds * time.Second)
assert.WithinDuration(t, expectedDeadline, deadline, time.Second)
}
func TestRuntimeInstallWithDockerRuntime(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "docker",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/docker",
DockerdFile: "/path/to/dockerd.tar.gz",
HostIP: testHostIP,
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
var capturedDomain, capturedStorage, capturedDockerFile, capturedHostIP string
patches.ApplyFunc(dockerd.EnsureDockerServer, func(domain, storage, dockerFile, hostIP string) error {
capturedDomain = domain
capturedStorage = storage
capturedDockerFile = dockerFile
capturedHostIP = hostIP
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
assert.Equal(t, "registry.example.com", capturedDomain)
assert.Equal(t, "/var/lib/docker", capturedStorage)
assert.Equal(t, "/path/to/dockerd.tar.gz", capturedDockerFile)
assert.Equal(t, testHostIP, capturedHostIP)
}
func TestRuntimeInstallWithContainerdRuntime(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(cond.Install, func(domain, port, storage, containerdFile, caFile string) error {
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
}
func TestRuntimeInstallWithCniPlugin(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "containerd",
Domain: "registry.example.com",
RuntimeStorage: "/var/lib/containerd",
ContainerdFile: "/path/to/containerd.tar.gz",
CAFile: "/path/to/ca.crt",
CniPluginFile: "/path/to/cni.tar.gz",
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(cond.Install, func(domain, storage, containerdFile, caFile string) error {
return nil
})
var capturedCniPluginFile string
patches.ApplyFunc(cond.CniPluginInstall, func(cniPluginFile string) error {
capturedCniPluginFile = cniPluginFile
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
assert.Equal(t, "/path/to/cni.tar.gz", capturedCniPluginFile)
}
func TestStartLocalKubernetesWithBothAvailable(t *testing.T) {
cfg := k3s.Config{
HostIP: testHostIP,
KubernetesPort: testKubernetesPort,
}
localImage := "test-image:latest"
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return true })
patches.ApplyFunc(IsContainerd, func() bool { return true })
dockerCalled := false
containerdCalled := false
patches.ApplyFunc(k3s.StartK3sWithDocker, func(c k3s.Config, image string) error {
dockerCalled = true
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
})
patches.ApplyFunc(k3s.EnsureDirExists, func(dir string) error {
return nil
})
patches.ApplyFunc(k3s.StartK3sWithContainerd, func(c k3s.Config, image string) error {
containerdCalled = true
assert.Equal(t, cfg, c)
assert.Equal(t, localImage, image)
return nil
})
err := StartLocalKubernetes(cfg, localImage)
assert.NoError(t, err)
assert.True(t, dockerCalled)
assert.True(t, containerdCalled)
}
func TestStartLocalKubernetesWithNeitherAvailable(t *testing.T) {
cfg := k3s.Config{
HostIP: testHostIP,
KubernetesPort: testKubernetesPort,
}
localImage := "test-image:latest"
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
err := StartLocalKubernetes(cfg, localImage)
assert.NoError(t, err)
}
func TestRuntimeConfigWithEmptyValues(t *testing.T) {
cfg := &RuntimeConfig{}
assert.Equal(t, "", cfg.Runtime)
assert.Equal(t, "", cfg.RuntimeStorage)
assert.Equal(t, "", cfg.Domain)
assert.Equal(t, "", cfg.ContainerdFile)
assert.Equal(t, "", cfg.CniPluginFile)
assert.Equal(t, "", cfg.DockerdFile)
assert.Equal(t, "", cfg.HostIP)
assert.Equal(t, "", cfg.CAFile)
}
func TestRuntimeInstallWithEmptyConfig(t *testing.T) {
cfg := RuntimeConfig{}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(dockerd.EnsureDockerServer, func(domain, storage, dockerFile, hostIP string) error {
assert.Equal(t, "", domain)
assert.Equal(t, "", storage)
assert.Equal(t, "", dockerFile)
assert.Equal(t, "", hostIP)
return nil
})
err := RuntimeInstall(cfg)
assert.Error(t, err)
}
func TestRuntimeInstallDockerRuntimeWithEmptyValues(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "docker",
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(dockerd.EnsureDockerServer, func(domain, storage, dockerFile, hostIP string) error {
assert.Equal(t, "", domain)
assert.Equal(t, "", storage)
assert.Equal(t, "", dockerFile)
assert.Equal(t, "", hostIP)
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
}
func TestRuntimeInstallContainerdRuntimeWithEmptyValues(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "containerd",
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(cond.Install, func(domain, storage, containerdFile, caFile string) error {
assert.Equal(t, "", domain)
assert.Equal(t, "", storage)
assert.Equal(t, "", containerdFile)
assert.Equal(t, "", caFile)
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
}
func TestRuntimeInstallContainerdWithCniPluginEmpty(t *testing.T) {
cfg := RuntimeConfig{
Runtime: "containerd",
CniPluginFile: "",
}
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(IsDocker, func() bool { return false })
patches.ApplyFunc(IsContainerd, func() bool { return false })
patches.ApplyFunc(cond.Install, func(domain, storage, containerdFile, caFile string) error {
return nil
})
patches.ApplyFunc(cond.CniPluginInstall, func(cniPluginFile string) error {
t.Error("CniPluginInstall should not be called when CniPluginFile is empty")
return nil
})
err := RuntimeInstall(cfg)
assert.NoError(t, err)
}