mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-17 03:57:04 +02:00
Fixes: #689, #690 Refactor container inspection code into a package of its own with some rudimentary tests. Use this package consistently in osd commands dealing with containers. Improvements for the next PRs: * implement API to fetch info about container by ID (to avoid fetching full list) * handle and display errors on client side, not to the log of the server * more tests, including k8s containers (how can we do that?) Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
148 lines
4.1 KiB
Go
148 lines
4.1 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 containers_test
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"os"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/containerd/containerd"
|
|
"github.com/containerd/containerd/namespaces"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/talos-systems/talos/internal/app/init/pkg/system/events"
|
|
"github.com/talos-systems/talos/internal/app/init/pkg/system/runner"
|
|
containerdrunner "github.com/talos-systems/talos/internal/app/init/pkg/system/runner/containerd"
|
|
"github.com/talos-systems/talos/internal/app/init/pkg/system/runner/process"
|
|
"github.com/talos-systems/talos/internal/pkg/constants"
|
|
"github.com/talos-systems/talos/internal/pkg/containers"
|
|
"github.com/talos-systems/talos/pkg/userdata"
|
|
)
|
|
|
|
const (
|
|
containerdNamespace = "inspecttest"
|
|
busyboxImage = "docker.io/library/busybox:latest"
|
|
)
|
|
|
|
func MockEventSink(state events.ServiceState, message string, args ...interface{}) {
|
|
}
|
|
|
|
type ContainersSuite struct {
|
|
suite.Suite
|
|
|
|
tmpDir string
|
|
|
|
containerdRunner runner.Runner
|
|
containerdWg sync.WaitGroup
|
|
|
|
client *containerd.Client
|
|
image containerd.Image
|
|
}
|
|
|
|
// nolint: dupl
|
|
func (suite *ContainersSuite) SetupSuite() {
|
|
var err error
|
|
|
|
args := &runner.Args{
|
|
ID: "containerd",
|
|
ProcessArgs: []string{"/rootfs/bin/containerd"},
|
|
}
|
|
|
|
suite.tmpDir, err = ioutil.TempDir("", "talos")
|
|
suite.Require().NoError(err)
|
|
|
|
suite.containerdRunner = process.NewRunner(
|
|
&userdata.UserData{},
|
|
args,
|
|
runner.WithLogPath(suite.tmpDir),
|
|
runner.WithEnv([]string{"PATH=/rootfs/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 = containerd.New(constants.ContainerdAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
ctx := namespaces.WithNamespace(context.Background(), containerdNamespace)
|
|
|
|
suite.image, err = suite.client.Pull(ctx, busyboxImage, containerd.WithPullUnpack)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
func (suite *ContainersSuite) TearDownSuite() {
|
|
suite.Require().NoError(suite.client.Close())
|
|
|
|
suite.Require().NoError(suite.containerdRunner.Stop())
|
|
suite.containerdWg.Wait()
|
|
|
|
suite.Require().NoError(os.RemoveAll(suite.tmpDir))
|
|
}
|
|
|
|
func (suite *ContainersSuite) TestRunSuccess() {
|
|
r := containerdrunner.NewRunner(&userdata.UserData{}, &runner.Args{
|
|
ID: "test",
|
|
ProcessArgs: []string{"/bin/sh", "-c", "sleep 3600"},
|
|
},
|
|
runner.WithLogPath(suite.tmpDir),
|
|
runner.WithNamespace(containerdNamespace),
|
|
runner.WithContainerImage(busyboxImage),
|
|
)
|
|
|
|
suite.Require().NoError(r.Open(context.Background()))
|
|
defer func() { suite.Assert().NoError(r.Close()) }()
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
suite.Assert().NoError(r.Run(MockEventSink))
|
|
}()
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
i, err := containers.NewInspector(context.Background(), containerdNamespace)
|
|
suite.Assert().NoError(err)
|
|
|
|
pods, err := i.Pods()
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Len(pods, 1)
|
|
suite.Assert().Equal("test", pods[0].Name)
|
|
suite.Assert().Equal("", pods[0].Sandbox)
|
|
suite.Assert().Len(pods[0].Containers, 1)
|
|
suite.Assert().Equal("test", pods[0].Containers[0].Display)
|
|
suite.Assert().Equal("test", pods[0].Containers[0].Name)
|
|
suite.Assert().Equal("test", pods[0].Containers[0].ID)
|
|
suite.Assert().Equal(busyboxImage, pods[0].Containers[0].Image)
|
|
suite.Assert().Equal(containerd.Running, pods[0].Containers[0].Status.Status)
|
|
suite.Assert().NotNil(pods[0].Containers[0].Metrics)
|
|
|
|
suite.Assert().NoError(i.Close())
|
|
|
|
suite.Assert().NoError(r.Stop())
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestContainersSuite(t *testing.T) {
|
|
if os.Getuid() != 0 {
|
|
t.Skip("can't run the test as non-root")
|
|
}
|
|
_, err := os.Stat("/rootfs/bin/containerd")
|
|
if err != nil {
|
|
t.Skip("containerd binary is not available, skipping the test")
|
|
}
|
|
|
|
suite.Run(t, new(ContainersSuite))
|
|
}
|