diff --git a/.github/workflows/self_hosted_e2e.yaml b/.github/workflows/self_hosted_e2e.yaml index 799b5683f..b29db0517 100644 --- a/.github/workflows/self_hosted_e2e.yaml +++ b/.github/workflows/self_hosted_e2e.yaml @@ -47,7 +47,7 @@ jobs: matrix: os: [macos-latest, ubuntu-latest, windows-latest] target_arch: [amd64] - dapr_install_mode: [slim, complete] + dapr_install_mode: [slim, complete, complete_containerd] include: - os: ubuntu-latest target_os: linux @@ -58,6 +58,8 @@ jobs: exclude: - os: windows-latest dapr_install_mode: complete + - os: windows-latest + dapr_install_mode: complete_containerd steps: - name: Check out code into the Go module directory uses: actions/checkout@v3 @@ -108,6 +110,43 @@ jobs: podman machine init podman machine start echo "CONTAINER_RUNTIME=podman" >> $GITHUB_ENV + - name: Install containerd - MacOS + if: matrix.os == 'macos-latest' && matrix.dapr_install_mode == 'complete_containerd' + run: | + colima start --runtime containerd + colima nerdctl install + echo "CONTAINER_RUNTIME=containerd" >> $GITHUB_ENV + - name: Install containerd - Linux + if: matrix.os == 'ubuntu-latest' && matrix.dapr_install_mode == 'complete_containerd' + run: | + # remove moby-runc, version not match + sudo apt remove moby-runc + # install containerd and rootlesskit, testing requires rootless mode + sudo apt install -y containerd rootlesskit + wget -q https://github.com/containerd/nerdctl/releases/download/v1.3.0/nerdctl-1.3.0-linux-amd64.tar.gz -O nerdctl-linux-amd64.tar.gz + # install nerdctl + tar xvf ./nerdctl-linux-amd64.tar.gz -C /usr/local/bin/ + containerd-rootless-setuptool.sh install + # update cni to new version + wget -q https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz -O cni-plugins-linux-amd64.tgz + sudo tar xvf ./cni-plugins-linux-amd64.tgz -C /usr/lib/cni/ + echo "CONTAINER_RUNTIME=containerd" >> $GITHUB_ENV + - name: Install contianerd - Windows + if: matrix.os == 'windows-latest' && matrix.dapr_install_mode == 'complete_containerd' + run: | + # install nerdctl + $NVersion="1.3.0" + curl.exe -L https://github.com/containerd/nerdctl/releases/download/v$NVersion/nerdctl-$NVersion-windows-amd64.tar.gz -o nerdctl-windows-amd64.tar.gz + tar.exe xvf .\nerdctl-windows-amd64.tar.gz -C "$(go env GOPATH)\bin" + # Download and extract desired containerd Windows binaries + $Version="1.7.0" + curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz + tar.exe xvf .\containerd-windows-amd64.tar.gz && cd .\bin\ + .\containerd.exe config default | Out-File config.toml -Encoding ascii + # Register and start service + .\containerd.exe --register-service + Start-Service containerd + echo "CONTAINER_RUNTIME=containerd" >> $GITHUB_ENV - name: Determine latest Dapr Runtime version including Pre-releases if: github.base_ref == 'master' run: | diff --git a/README.md b/README.md index 6b2c30edb..ab8e446d3 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,46 @@ The Dapr CLI allows you to setup Dapr on your local dev machine or on a Kubernet ### Prerequisites -On default, during initialization the Dapr CLI will install the Dapr binaries as well as setup a developer environment to help you get started easily with Dapr. This environment uses Docker containers, therefore Docker needs to be installed. If you prefer to run Dapr without this environment and no dependency on Docker, after installation of the CLI make sure to follow the instructions to initialize Dapr using [slim init](#slim-init). +On default, during initialization the Dapr CLI will install the Dapr binaries as well as setup a developer environment to help you get started easily with Dapr. This environment uses `Docker`, `Podman` or `Containerd` containers, therefore container runtime needs to be installed. If you prefer to run Dapr without this environment and without any container dependencies, after installation of the CLI make sure to follow the instructions to initialize Dapr using [slim init](#slim-init). -Note, if you are a new user, it is strongly recommended to install Docker and use the regular init command. +>__Note, if you are a new user, it is strongly recommended to install Docker and use the regular init command.__ -* Install [Docker](https://docs.docker.com/install/) +### Choosing a container runtime ->__Note: On Windows, Docker must be running in Linux Containers mode__ +* [Docker](https://docs.docker.com/install/) (recommended for new users) + + >__Note: On Windows, Docker must be running in Linux Containers mode__ + +* [Podman](https://podman-desktop.io/docs/Installation) + +* `Containerd` + + >__Windows and Linux__ + + * Step 1: Install [Containerd](https://github.com/containerd/containerd/blob/main/docs/getting-started.md). + + * Step 2: Install [nerdctl](https://github.com/containerd/nerdctl/blob/main/docs/installation.md). + + >__MacOS__ + >> `containerd` and `nerdctl` are not directly supported on macOS. Instead, you need to choose `lima`, `colima`, or `rancher-desktop` to get this feature. + + * [Lima](https://github.com/lima-vm/lima) + + ```bash + brew install lima + limactl start + ln -s $(which nerdctl.lima) /usr/local/bin/nerdctl + ``` + + * [Colima](https://github.com/abiosoft/colima) + + ```bash + brew install colima + colima start --runtime containerd + colima nerdctl install + ``` + + * [Rancher-desktop](https://docs.rancherdesktop.io/getting-started/installation#installing-rancher-desktop-on-macos) ### Installing Dapr CLI @@ -139,7 +172,7 @@ Runtime version: v1.0.0 #### Install with mariner images -You can install Dapr Runtime using mariner images using the `--image-variant` flag. +You can install Dapr Runtime using mariner images using the `--image-variant` flag. ```bash # Installing Dapr with Mariner images @@ -178,7 +211,7 @@ docker run --name "dapr_zipkin" --restart always -d -p 9411:9411 openzipkin/zipk docker run --name "dapr_redis" --restart always -d -p 6379:6379 redis ``` -Alternatively to the above, you can also have slim installation as well to install dapr without running any Docker containers in airgap mode. +Alternatively to the above, you can also have slim installation as well to install dapr without running any Docker containers in airgap mode. ```bash ./dapr init --slim --from-dir . @@ -292,7 +325,7 @@ Output should look like as follows: All available [Helm Chart values](https://github.com/dapr/dapr/tree/master/charts/dapr#configuration) can be set by using the `--set` flag: ```bash -dapr init -k --set global.tag=1.0.0 --set dapr_operator.logLevel=error +dapr init -k --set global.tag=1.0.0 --set dapr_operator.logLevel=error ``` #### Installing to a custom namespace @@ -356,7 +389,7 @@ The example above shows how to upgrade from your current version to version `1.0 All available [Helm Chart values](https://github.com/dapr/dapr/tree/master/charts/dapr#configuration) can be set by using the `--set` flag: ```bash -dapr upgrade -k --runtime-version=1.0.0 --set global.tag=my-tag --set dapr_operator.logLevel=error +dapr upgrade -k --runtime-version=1.0.0 --set global.tag=my-tag --set dapr_operator.logLevel=error ``` *Note: do not use the `dapr upgrade` command if you're upgrading from 0.x versions of Dapr* diff --git a/cmd/init.go b/cmd/init.go index 5257a35ed..0290e0dd3 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -49,7 +49,7 @@ var ( var InitCmd = &cobra.Command{ Use: "init", Short: "Install Dapr on supported hosting platforms. Supported platforms: Kubernetes and self-hosted", - PreRun: func(cmd *cobra.Command, args []string) { + PreRun: func(cmd *cobra.Command, _ []string) { viper.BindPFlag("network", cmd.Flags().Lookup("network")) viper.BindPFlag("image-registry", cmd.Flags().Lookup("image-registry")) @@ -92,7 +92,7 @@ dapr init --runtime-path # See more at: https://docs.dapr.io/getting-started/ `, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { print.PendingStatusEvent(os.Stdout, "Making the jump to hyperspace...") imageRegistryFlag := strings.TrimSpace(viper.GetString("image-registry")) @@ -161,7 +161,7 @@ dapr init --runtime-path } if !utils.IsValidContainerRuntime(containerRuntime) { - print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker and podman.") + print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker, podman and containerd.") os.Exit(1) } err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant, daprRuntimePath) @@ -215,7 +215,7 @@ func init() { InitCmd.Flags().BoolP("help", "h", false, "Print this help message") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-registry", "", "Custom/private docker image repository URL") - InitCmd.Flags().StringVarP(&containerRuntime, "container-runtime", "", defaultContainerRuntime, "The container runtime to use. Supported values are docker (default) and podman") + InitCmd.Flags().StringVarP(&containerRuntime, "container-runtime", "", defaultContainerRuntime, "The container runtime to use. Supported values are docker (default), podman and containerd") InitCmd.Flags().StringVarP(&caRootCertificateFile, "ca-root-certificate", "", "", "The root certificate file") InitCmd.Flags().StringVarP(&issuerPrivateKeyFile, "issuer-private-key", "", "", "The issuer certificate private key") InitCmd.Flags().StringVarP(&issuerPublicCertificateFile, "issuer-public-certificate", "", "", "The issuer certificate") diff --git a/cmd/uninstall.go b/cmd/uninstall.go index a4885c935..c68ee61b4 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -52,11 +52,11 @@ dapr uninstall -k # This will remove the .dapr directory present in the path dapr uninstall --runtime-path `, - PreRun: func(cmd *cobra.Command, args []string) { + PreRun: func(cmd *cobra.Command, _ []string) { viper.BindPFlag("network", cmd.Flags().Lookup("network")) viper.BindPFlag("install-path", cmd.Flags().Lookup("install-path")) }, - Run: func(cmd *cobra.Command, args []string) { + Run: func(*cobra.Command, []string) { var err error if uninstallKubernetes { @@ -69,7 +69,7 @@ dapr uninstall --runtime-path err = kubernetes.Uninstall(uninstallNamespace, uninstallAll, timeout) } else { if !utils.IsValidContainerRuntime(uninstallContainerRuntime) { - print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker and podman.") + print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker, podman and containerd.") os.Exit(1) } print.InfoStatusEvent(os.Stdout, "Removing Dapr from your machine...") @@ -92,6 +92,6 @@ func init() { UninstallCmd.Flags().String("network", "", "The Docker network from which to remove the Dapr runtime") UninstallCmd.Flags().StringVarP(&uninstallNamespace, "namespace", "n", "dapr-system", "The Kubernetes namespace to uninstall Dapr from") UninstallCmd.Flags().BoolP("help", "h", false, "Print this help message") - UninstallCmd.Flags().StringVarP(&uninstallContainerRuntime, "container-runtime", "", "docker", "The container runtime to use. Supported values are docker (default) and podman") + UninstallCmd.Flags().StringVarP(&uninstallContainerRuntime, "container-runtime", "", "docker", "The container runtime to use. Supported values are docker (default), podman and containerd") RootCmd.AddCommand(UninstallCmd) } diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 6cf7cbd6a..70eec87a7 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -161,9 +161,8 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod fromDir = strings.TrimSpace(fromDir) setAirGapInit(fromDir) if !slimMode { - // If --slim installation is not requested, check if docker is installed. - conatinerRuntimeAvailable := utils.IsDockerInstalled() || utils.IsPodmanInstalled() - if !conatinerRuntimeAvailable { + // If --slim installation is not requested, check if the container runtime is installed. + if !utils.ContainerRuntimeAvailable(containerRuntime) { return fmt.Errorf("could not connect to %s. %s may not be installed or running", containerRuntime, containerRuntime) } @@ -363,10 +362,8 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { ) if info.dockerNetwork != "" { - args = append( - args, - "--network", info.dockerNetwork, - "--network-alias", DaprZipkinContainerName) + networks := withContainerNetwork(info.containerRuntime, info.dockerNetwork, DaprZipkinContainerName) + args = append(args, networks...) } else { args = append( args, @@ -430,10 +427,8 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { ) if info.dockerNetwork != "" { - args = append( - args, - "--network", info.dockerNetwork, - "--network-alias", DaprRedisContainerName) + networks := withContainerNetwork(info.containerRuntime, info.dockerNetwork, DaprRedisContainerName) + args = append(args, networks...) } else { args = append( args, @@ -510,9 +505,8 @@ func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, info initIn } if info.dockerNetwork != "" { - args = append(args, - "--network", info.dockerNetwork, - "--network-alias", DaprPlacementContainerName) + networks := withContainerNetwork(info.containerRuntime, info.dockerNetwork, DaprPlacementContainerName) + args = append(args, networks...) } else { osPort := 50005 if runtime.GOOS == daprWindowsOS { @@ -1011,6 +1005,19 @@ func createDefaultConfiguration(zipkinHost, filePath string) error { return err } +// withContainerNetwork connect a container to a network. +// Network alias is now only parsed by docker, +// `podman` is only compatible with docker commands +// and does not really implement this feature. +// `containerd` does not support network alias. +func withContainerNetwork(containerCmd, network, containerName string) []string { + networks := []string{"--network", network} + if utils.GetContainerRuntimeCmd(containerCmd) == string(utils.DOCKER) { + networks = append(networks, "--network-alias", containerName) + } + return networks +} + func checkAndOverWriteFile(filePath string, b []byte) error { _, err := os.Stat(filePath) if os.IsNotExist(err) { diff --git a/pkg/standalone/uninstall.go b/pkg/standalone/uninstall.go index 29fee9b60..c680ef5eb 100644 --- a/pkg/standalone/uninstall.go +++ b/pkg/standalone/uninstall.go @@ -90,11 +90,9 @@ func Uninstall(uninstallAll bool, dockerNetwork string, containerRuntime string, print.WarningStatusEvent(os.Stdout, "WARNING: could not delete dapr bin dir: %s", daprBinDir) } - containerRuntime = strings.TrimSpace(containerRuntime) - runtimeCmd := utils.GetContainerRuntimeCmd(containerRuntime) - conatinerRuntimeAvailable := false - conatinerRuntimeAvailable = utils.IsDockerInstalled() || utils.IsPodmanInstalled() - if conatinerRuntimeAvailable { + if utils.ContainerRuntimeAvailable(containerRuntime) { + containerRuntime = strings.TrimSpace(containerRuntime) + runtimeCmd := utils.GetContainerRuntimeCmd(containerRuntime) containerErrs = removeContainers(uninstallPlacementContainer, uninstallAll, dockerNetwork, runtimeCmd) } diff --git a/tests/e2e/standalone/init_test.go b/tests/e2e/standalone/init_test.go index 14a688bc2..3221206e4 100644 --- a/tests/e2e/standalone/init_test.go +++ b/tests/e2e/standalone/init_test.go @@ -188,47 +188,87 @@ func TestStandaloneInit(t *testing.T) { // this test is automatically skipped. func verifyContainers(t *testing.T, daprRuntimeVersion string) { t.Run("verifyContainers", func(t *testing.T) { - if isSlimMode() { + switch { + case isSlimMode(): t.Log("Skipping container verification because of slim installation") - return + case containerRuntime() == "containerd": + verifyContainerdRuntime(t, daprRuntimeVersion) + default: + verifyDockerRuntime(t, daprRuntimeVersion) } + }) +} - cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv) - require.NoError(t, err) +func verifyContainerdRuntime(t *testing.T, daprRuntimeVersion string) { + ret, err := spawn.Command("nerdctl", "ps", "--filter", "name=dapr", "--format", "{{.Names}} {{.Image}}") + require.NoError(t, err) - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) - require.NoError(t, err) + daprContainers := map[string]string{ + "dapr_placement": daprRuntimeVersion, + "dapr_zipkin": "", + "dapr_redis": "", + } - daprContainers := map[string]string{ - "dapr_placement": daprRuntimeVersion, - "dapr_zipkin": "", - "dapr_redis": "", + // convert to map + containers := map[string]string{} + for _, item := range strings.Split(ret, "\n") { + if split := strings.Split(item, " "); len(split) > 1 { + containers[split[0]] = split[1] } + } - for _, container := range containers { - t.Logf("Found container: %v %s %s\n", container.Names, container.Image, container.State) - if container.State != "running" { - continue - } - name := strings.TrimPrefix(container.Names[0], "/") - if expectedVersion, ok := daprContainers[name]; ok { - if expectedVersion != "" { - versionIndex := strings.LastIndex(container.Image, ":") - if versionIndex == -1 { - continue - } - version := container.Image[versionIndex+1:] - if version != expectedVersion { - continue - } + for name, image := range containers { + t.Logf("Found container: %v %s\n", name, image) + if expectedVersion, ok := daprContainers[name]; ok { + if expectedVersion != "" { + versionIndex := strings.LastIndex(image, ":") + if versionIndex == -1 || image[versionIndex+1:] != expectedVersion { + continue } + } + delete(daprContainers, name) + } + } + + assert.Empty(t, daprContainers, "Missing containers: %v", daprContainers) +} - delete(daprContainers, name) +func verifyDockerRuntime(t *testing.T, daprRuntimeVersion string) { + cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv) + require.NoError(t, err) + + containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) + require.NoError(t, err) + + daprContainers := map[string]string{ + "dapr_placement": daprRuntimeVersion, + "dapr_zipkin": "", + "dapr_redis": "", + } + + for _, container := range containers { + t.Logf("Found container: %v %s %s\n", container.Names, container.Image, container.State) + if container.State != "running" { + continue + } + name := strings.TrimPrefix(container.Names[0], "/") + if expectedVersion, ok := daprContainers[name]; ok { + if expectedVersion != "" { + versionIndex := strings.LastIndex(container.Image, ":") + if versionIndex == -1 { + continue + } + version := container.Image[versionIndex+1:] + if version != expectedVersion { + continue + } } + + delete(daprContainers, name) } + } - assert.Empty(t, daprContainers, "Missing containers: %v", daprContainers) - }) + assert.Empty(t, daprContainers, "Missing containers: %v", daprContainers) } // verifyBinaries ensures that the correct binaries are present in the correct path. diff --git a/tests/e2e/standalone/uninstall_test.go b/tests/e2e/standalone/uninstall_test.go index ae1545a99..5ad5c6ea2 100644 --- a/tests/e2e/standalone/uninstall_test.go +++ b/tests/e2e/standalone/uninstall_test.go @@ -23,6 +23,7 @@ import ( "strings" "testing" + "github.com/dapr/cli/tests/e2e/spawn" "github.com/docker/docker/api/types" dockerClient "github.com/docker/docker/client" "github.com/stretchr/testify/assert" @@ -57,11 +58,17 @@ func TestStandaloneUninstall(t *testing.T) { // verifyNoContainers verifies that no Dapr containers are running. func verifyNoContainers(t *testing.T) { - if isSlimMode() { + switch { + case isSlimMode(): t.Log("Skipping verifyNoContainers test in slim mode") - return + case containerRuntime() == "containerd": + verifyNoContainerdRuntime(t) + default: + verifyNoDockerRuntime(t) } +} +func verifyNoDockerRuntime(t *testing.T) { cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv) require.NoError(t, err) @@ -85,3 +92,19 @@ func verifyNoContainers(t *testing.T) { // If any Dapr containers are still running after uninstall, this assertion will fail. assert.Equal(t, 3, len(daprContainers), "Found Dapr containers still running") } + +func verifyNoContainerdRuntime(t *testing.T) { + ret, err := spawn.Command("nerdctl", "ps", "--filter", "name=dapr", "--format", "{{.Names}}") + require.NoError(t, err) + + daprContainers := []string{ + "dapr_placement", + "dapr_zipkin", + "dapr_redis", + } + + containers := strings.Split(ret, "\n") + for _, container := range containers { + assert.NotContains(t, daprContainers, container, "Found Dapr containers still running") + } +} diff --git a/utils/utils.go b/utils/utils.go index 262c3f674..e85cf6bc2 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -39,8 +39,11 @@ import ( type ContainerRuntime string const ( - DOCKER ContainerRuntime = "docker" - PODMAN ContainerRuntime = "podman" + DOCKER ContainerRuntime = "docker" + PODMAN ContainerRuntime = "podman" + CONTAINERD ContainerRuntime = "containerd" + + NERDCTL = "nerdctl" marinerImageVariantName = "mariner" @@ -51,21 +54,26 @@ const ( ) // IsValidContainerRuntime checks if the input is a valid container runtime. -// Valid container runtimes are docker and podman. +// Valid container runtimes are docker and podman and containerd. func IsValidContainerRuntime(containerRuntime string) bool { containerRuntime = strings.TrimSpace(containerRuntime) - return containerRuntime == string(DOCKER) || containerRuntime == string(PODMAN) + return containerRuntime == string(DOCKER) || containerRuntime == string(PODMAN) || containerRuntime == string(CONTAINERD) } // GetContainerRuntimeCmd returns a valid container runtime to be used by CLI operations. -// If the input is a valid container runtime, it is returned as is. +// If the input is a valid container runtime, the client tool is returned. // Otherwise the default container runtime, docker, is returned. func GetContainerRuntimeCmd(containerRuntime string) string { - if IsValidContainerRuntime(containerRuntime) { - return strings.TrimSpace(containerRuntime) + switch strings.TrimSpace(containerRuntime) { + case string(CONTAINERD): + // containerd runtime use nerdctl tool. + return NERDCTL + case string(PODMAN): + return string(PODMAN) + default: + // Default to docker. + return string(DOCKER) } - // Default to docker. - return string(DOCKER) } // Contains returns true if vs contains x. @@ -136,15 +144,15 @@ func RunCmdAndWait(name string, args ...string) (string, error) { return "", err } - resp, err := io.ReadAll(stdout) - if err != nil { - return "", err - } errB, err := io.ReadAll(stderr) if err != nil { //nolint return "", nil } + resp, err := io.ReadAll(stdout) + if err != nil { + return "", err + } err = cmd.Wait() if err != nil { @@ -192,6 +200,27 @@ func IsPodmanInstalled() bool { return true } +// IsContainerdInstalled checks whether nerdctl and containerd is installed/running. +func IsContainerdInstalled() bool { + if _, err := RunCmdAndWait("nerdctl", "info"); err != nil { + print.FailureStatusEvent(os.Stderr, err.Error()) + return false + } + return true +} + +func ContainerRuntimeAvailable(containerRuntime string) bool { + containerRuntime = strings.TrimSpace(containerRuntime) + switch ContainerRuntime(containerRuntime) { + case PODMAN: + return IsPodmanInstalled() + case CONTAINERD: + return IsContainerdInstalled() + default: + return IsDockerInstalled() + } +} + // IsDaprListeningOnPort checks if Dapr is litening to a given port. func IsDaprListeningOnPort(port int, timeout time.Duration) error { start := time.Now() diff --git a/utils/utils_test.go b/utils/utils_test.go index 222a8b20e..5ad0a4ee0 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -31,6 +31,18 @@ func TestContainerRuntimeUtils(t *testing.T) { expected string valid bool }{ + { + name: "containerd runtime is valid, and nerdctl is returned", + input: "containerd", + expected: "nerdctl", + valid: true, + }, + { + name: "containerd runtime with extra spaces is valid, and nerdctl is returned", + input: " containerd ", + expected: "nerdctl", + valid: true, + }, { name: "podman runtime is valid, and is returned as is", input: "podman", @@ -177,7 +189,9 @@ func TestGetVersionAndImageVariant(t *testing.T) { func TestValidateFilePaths(t *testing.T) { dirName := createTempDir(t, "test_validate_paths") - defer cleanupTempDir(t, dirName) + t.Cleanup(func() { + cleanupTempDir(t, dirName) + }) validFile := createTempFile(t, dirName, "valid_test_file.yaml") testcases := []struct { name string @@ -317,7 +331,9 @@ func TestResolveHomeDir(t *testing.T) { func TestReadFile(t *testing.T) { fileName := createTempFile(t, "", "test_read_file") - defer cleanupTempDir(t, fileName) + t.Cleanup(func() { + cleanupTempDir(t, fileName) + }) testcases := []struct { name string input string