talos/internal/pkg/cri/cri_test.go
Andrew Rynhard d4c202438c refactor: set CRI config to /etc/cri/containerd.toml
This changes the CRI specific containerd instance's config to a
different path.

Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
2019-12-04 19:32:00 -08:00

218 lines
5.9 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package cri_test
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"sync"
"testing"
"time"
"github.com/stretchr/testify/suite"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/events"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/process"
"github.com/talos-systems/talos/internal/pkg/cri"
"github.com/talos-systems/talos/pkg/constants"
)
const (
busyboxImage = "docker.io/library/busybox:1.30.1"
)
func MockEventSink(state events.ServiceState, message string, args ...interface{}) {
}
// nolint: maligned
type CRISuite struct {
suite.Suite
tmpDir string
containerdRunner runner.Runner
containerdWg sync.WaitGroup
containerdAddress string
client *cri.Client
ctx context.Context
ctxCancel context.CancelFunc
}
// nolint: dupl
func (suite *CRISuite) SetupSuite() {
var err error
suite.tmpDir, err = ioutil.TempDir("", "talos")
suite.Require().NoError(err)
stateDir, rootDir := filepath.Join(suite.tmpDir, "state"), filepath.Join(suite.tmpDir, "root")
suite.Require().NoError(os.Mkdir(stateDir, 0777))
suite.Require().NoError(os.Mkdir(rootDir, 0777))
suite.containerdAddress = filepath.Join(suite.tmpDir, "run.sock")
args := &runner.Args{
ID: "containerd",
ProcessArgs: []string{
"/bin/containerd",
"--address", suite.containerdAddress,
"--state", stateDir,
"--root", rootDir,
"--config", constants.CRIContainerdConfig,
},
}
suite.containerdRunner = process.NewRunner(
false,
args,
runner.WithLogPath(suite.tmpDir),
runner.WithEnv([]string{"PATH=/bin:" + constants.PATH}),
)
suite.Require().NoError(suite.containerdRunner.Open(context.Background()))
suite.containerdWg.Add(1)
go func() {
defer suite.containerdWg.Done()
defer func() { suite.Require().NoError(suite.containerdRunner.Close()) }()
suite.Require().NoError(suite.containerdRunner.Run(MockEventSink))
}()
suite.client, err = cri.NewClient("unix:"+suite.containerdAddress, 30*time.Second)
suite.Require().NoError(err)
}
func (suite *CRISuite) TearDownSuite() {
suite.ctxCancel()
suite.Require().NoError(suite.client.Close())
suite.Require().NoError(suite.containerdRunner.Stop())
suite.containerdWg.Wait()
suite.Require().NoError(os.RemoveAll(suite.tmpDir))
}
func (suite *CRISuite) SetupTest() {
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 30*time.Second)
}
func (suite *CRISuite) TearDownTest() {
suite.ctxCancel()
}
func (suite *CRISuite) TestRunSandboxContainer() {
podSandboxConfig := &runtimeapi.PodSandboxConfig{
Metadata: &runtimeapi.PodSandboxMetadata{
Name: "etcd-master-1",
Uid: "ed1a599a53090941c9b4025c7e3e883d",
Namespace: "kube-system",
Attempt: 0,
},
Labels: map[string]string{
"io.kubernetes.pod.name": "etcd-master-1",
"io.kubernetes.pod.namespace": "kube-system",
},
LogDirectory: suite.tmpDir,
Linux: &runtimeapi.LinuxPodSandboxConfig{
SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{
NamespaceOptions: &runtimeapi.NamespaceOption{
Network: runtimeapi.NamespaceMode_NODE,
},
},
},
}
podSandboxID, err := suite.client.RunPodSandbox(suite.ctx, podSandboxConfig, "")
suite.Require().NoError(err)
suite.Require().Len(podSandboxID, 64)
imageRef, err := suite.client.PullImage(suite.ctx, &runtimeapi.ImageSpec{
Image: busyboxImage,
}, podSandboxConfig)
suite.Require().NoError(err)
_, err = suite.client.ImageStatus(suite.ctx, &runtimeapi.ImageSpec{
Image: imageRef,
})
suite.Require().NoError(err)
ctrID, err := suite.client.CreateContainer(suite.ctx, podSandboxID,
&runtimeapi.ContainerConfig{
Metadata: &runtimeapi.ContainerMetadata{
Name: "etcd",
},
Labels: map[string]string{
"io.kubernetes.container.name": "etcd",
"io.kubernetes.pod.name": "etcd-master-1",
"io.kubernetes.pod.namespace": "kube-system",
},
Annotations: map[string]string{
"io.kubernetes.container.restartCount": "1",
},
Image: &runtimeapi.ImageSpec{
Image: imageRef,
},
Command: []string{"/bin/sh", "-c", "sleep 3600"},
}, podSandboxConfig)
suite.Require().NoError(err)
suite.Require().Len(ctrID, 64)
err = suite.client.StartContainer(suite.ctx, ctrID)
suite.Require().NoError(err)
_, err = suite.client.ContainerStats(suite.ctx, ctrID)
suite.Require().NoError(err)
_, _, err = suite.client.ContainerStatus(suite.ctx, ctrID, true)
suite.Require().NoError(err)
err = suite.client.StopContainer(suite.ctx, ctrID, 10)
suite.Require().NoError(err)
err = suite.client.RemoveContainer(suite.ctx, ctrID)
suite.Require().NoError(err)
err = suite.client.StopPodSandbox(suite.ctx, podSandboxID)
suite.Require().NoError(err)
err = suite.client.RemovePodSandbox(suite.ctx, podSandboxID)
suite.Require().NoError(err)
}
func (suite *CRISuite) TestList() {
pods, err := suite.client.ListPodSandbox(suite.ctx, &runtimeapi.PodSandboxFilter{})
suite.Require().NoError(err)
suite.Require().Len(pods, 0)
containers, err := suite.client.ListContainers(suite.ctx, &runtimeapi.ContainerFilter{})
suite.Require().NoError(err)
suite.Require().Len(containers, 0)
containerStats, err := suite.client.ListContainerStats(suite.ctx, &runtimeapi.ContainerStatsFilter{})
suite.Require().NoError(err)
suite.Require().Len(containerStats, 0)
_, err = suite.client.ListImages(suite.ctx, &runtimeapi.ImageFilter{})
suite.Require().NoError(err)
}
func TestCRISuite(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("can't run the test as non-root")
}
_, err := os.Stat("/bin/containerd")
if err != nil {
t.Skip("containerd binary is not available, skipping the test")
}
suite.Run(t, new(CRISuite))
}