mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-01 13:14:33 +00:00
runtime: optimize test code
This PR includes these optimize changes: - Remove the dependency on the container engine. The old code uses runc to generate config.json and Docker to export rootfs, that will be heavy and need additional dependency. Using a fixed config for busybox image can avoid the heavy processing above. - Moved duplicate code to pkg/katatestutils package Fixes: #2752 Signed-off-by: bin <bin@hyper.sh>
This commit is contained in:
parent
41c49a7bf5
commit
273a1a9ac6
@ -30,9 +30,6 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// specConfig is the name of the file holding the containers configuration
|
||||
const specConfig = "config.json"
|
||||
|
||||
// arch is the architecture for the running program
|
||||
const arch = goruntime.GOARCH
|
||||
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -22,9 +21,7 @@ import (
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
@ -38,19 +35,12 @@ const (
|
||||
testFileMode = os.FileMode(0640)
|
||||
testExeFileMode = os.FileMode(0750)
|
||||
|
||||
// small docker image used to create root filesystems from
|
||||
testDockerImage = "busybox"
|
||||
|
||||
testBundle = "bundle"
|
||||
testConsole = "/dev/pts/999"
|
||||
)
|
||||
|
||||
var (
|
||||
// package variables set by calling TestMain()
|
||||
testDir = ""
|
||||
testBundleDir = ""
|
||||
tc ktu.TestConstraint
|
||||
ctrEngine = katautils.CtrEngine{}
|
||||
)
|
||||
|
||||
// testingImpl is a concrete mock RVC implementation used for testing
|
||||
@ -79,57 +69,6 @@ func init() {
|
||||
fmt.Printf("INFO: switching to fake virtcontainers implementation for testing\n")
|
||||
vci = testingImpl
|
||||
|
||||
var err error
|
||||
|
||||
fmt.Printf("INFO: creating test directory\n")
|
||||
testDir, err = ioutil.TempDir("", fmt.Sprintf("%s-", katautils.NAME))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create test directory: %v", err))
|
||||
}
|
||||
fmt.Printf("INFO: test directory is %v\n", testDir)
|
||||
|
||||
var output string
|
||||
for _, name := range katautils.DockerLikeCtrEngines {
|
||||
fmt.Printf("INFO: checking for container engine: %s\n", name)
|
||||
|
||||
output, err = ctrEngine.Init(name)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ctrEngine.Name == "" {
|
||||
panic(fmt.Sprintf("ERROR: Docker-like container engine not accessible to current user: %v (error %v)",
|
||||
output, err))
|
||||
}
|
||||
|
||||
// Do this now to avoid hitting the test timeout value due to
|
||||
// slow network response.
|
||||
fmt.Printf("INFO: ensuring required container image (%v) is available\n", testDockerImage)
|
||||
// Only hit the network if the image doesn't exist locally
|
||||
_, err = ctrEngine.Inspect(testDockerImage)
|
||||
if err == nil {
|
||||
fmt.Printf("INFO: container image %v already exists locally\n", testDockerImage)
|
||||
} else {
|
||||
fmt.Printf("INFO: pulling container image %v\n", testDockerImage)
|
||||
_, err = ctrEngine.Pull(testDockerImage)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
testBundleDir = filepath.Join(testDir, testBundle)
|
||||
err = os.MkdirAll(testBundleDir, testDirMode)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create bundle directory %v: %v", testBundleDir, err))
|
||||
}
|
||||
|
||||
fmt.Printf("INFO: creating OCI bundle in %v for tests to use\n", testBundleDir)
|
||||
err = realMakeOCIBundle(testBundleDir)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create OCI bundle: %v", err))
|
||||
}
|
||||
|
||||
tc = ktu.NewTestConstraint(false)
|
||||
}
|
||||
|
||||
@ -143,8 +82,6 @@ func resetCLIGlobals() {
|
||||
func runUnitTests(m *testing.M) {
|
||||
ret := m.Run()
|
||||
|
||||
os.RemoveAll(testDir)
|
||||
|
||||
os.Exit(ret)
|
||||
}
|
||||
|
||||
@ -232,146 +169,6 @@ func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConf
|
||||
}, nil
|
||||
}
|
||||
|
||||
// createOCIConfig creates an OCI configuration (spec) file in
|
||||
// the bundle directory specified (which must exist).
|
||||
func createOCIConfig(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !katautils.FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %s does not exist", bundleDir)
|
||||
}
|
||||
|
||||
var configCmd string
|
||||
|
||||
// Search for a suitable version of runc to use to generate
|
||||
// the OCI config file.
|
||||
for _, cmd := range []string{"docker-runc", "runc"} {
|
||||
fullPath, err := exec.LookPath(cmd)
|
||||
if err == nil {
|
||||
configCmd = fullPath
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if configCmd == "" {
|
||||
return errors.New("Cannot find command to generate OCI config file")
|
||||
}
|
||||
|
||||
_, err := utils.RunCommand([]string{configCmd, "spec", "--bundle", bundleDir})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specFile := filepath.Join(bundleDir, specConfig)
|
||||
if !katautils.FileExists(specFile) {
|
||||
return fmt.Errorf("generated OCI config file does not exist: %v", specFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createRootfs creates a minimal root filesystem below the specified
|
||||
// directory.
|
||||
func createRootfs(dir string) error {
|
||||
err := os.MkdirAll(dir, testDirMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := ctrEngine.Create(testDockerImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctrEngine.GetRootfs(container, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = ctrEngine.Rm(container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// realMakeOCIBundle will create an OCI bundle (including the "config.json"
|
||||
// config file) in the directory specified (which must already exist).
|
||||
//
|
||||
// XXX: Note that tests should *NOT* call this function - they should
|
||||
// XXX: instead call makeOCIBundle().
|
||||
func realMakeOCIBundle(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !katautils.FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %v does not exist", bundleDir)
|
||||
}
|
||||
|
||||
err := createOCIConfig(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note the unusual parameter (a directory, not the config
|
||||
// file to parse!)
|
||||
spec, err := compatoci.ParseConfigJSON(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the rootfs directory name the OCI config refers to
|
||||
ociRootPath := spec.Root.Path
|
||||
|
||||
rootfsDir := filepath.Join(bundleDir, ociRootPath)
|
||||
|
||||
if strings.HasPrefix(ociRootPath, "/") {
|
||||
return fmt.Errorf("Cannot handle absolute rootfs as bundle must be unique to each test")
|
||||
}
|
||||
|
||||
err = createRootfs(rootfsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create an OCI bundle in the specified directory.
|
||||
//
|
||||
// Note that the directory will be created, but it's parent is expected to exist.
|
||||
//
|
||||
// This function works by copying the already-created test bundle. Ideally,
|
||||
// the bundle would be recreated for each test, but createRootfs() uses
|
||||
// docker which on some systems is too slow, resulting in the tests timing
|
||||
// out.
|
||||
func makeOCIBundle(bundleDir string) error {
|
||||
from := testBundleDir
|
||||
to := bundleDir
|
||||
|
||||
// only the basename of bundleDir needs to exist as bundleDir
|
||||
// will get created by cp(1).
|
||||
base := filepath.Dir(bundleDir)
|
||||
|
||||
for _, dir := range []string{from, base} {
|
||||
if !katautils.FileExists(dir) {
|
||||
return fmt.Errorf("BUG: directory %v should exist", dir)
|
||||
}
|
||||
}
|
||||
|
||||
output, err := utils.RunCommandFull([]string{"cp", "-a", from, to}, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to copy test OCI bundle from %v to %v: %v (output: %v)", from, to, err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createCLIContextWithApp(flagSet *flag.FlagSet, app *cli.App) *cli.Context {
|
||||
ctx := cli.NewContext(app, flagSet, nil)
|
||||
|
||||
@ -390,69 +187,6 @@ func createCLIContext(flagset *flag.FlagSet) *cli.Context {
|
||||
return createCLIContextWithApp(flagset, cli.NewApp())
|
||||
}
|
||||
|
||||
func TestMakeOCIBundle(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundleDir := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundleDir)
|
||||
assert.NoError(err)
|
||||
|
||||
specFile := filepath.Join(bundleDir, specConfig)
|
||||
assert.True(katautils.FileExists(specFile))
|
||||
}
|
||||
|
||||
func TestCreateOCIConfig(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundleDir := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = createOCIConfig(bundleDir)
|
||||
// ENOENT
|
||||
assert.Error(err)
|
||||
|
||||
err = os.MkdirAll(bundleDir, testDirMode)
|
||||
assert.NoError(err)
|
||||
|
||||
err = createOCIConfig(bundleDir)
|
||||
assert.NoError(err)
|
||||
|
||||
specFile := filepath.Join(bundleDir, specConfig)
|
||||
assert.True(katautils.FileExists(specFile))
|
||||
}
|
||||
|
||||
func TestCreateRootfs(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
rootfsDir := filepath.Join(tmpdir, "rootfs")
|
||||
assert.False(katautils.FileExists(rootfsDir))
|
||||
|
||||
err = createRootfs(rootfsDir)
|
||||
assert.NoError(err)
|
||||
|
||||
// non-comprehensive list of expected directories
|
||||
expectedDirs := []string{"bin", "dev", "etc", "usr", "var"}
|
||||
|
||||
assert.True(katautils.FileExists(rootfsDir))
|
||||
|
||||
for _, dir := range expectedDirs {
|
||||
dirPath := filepath.Join(rootfsDir, dir)
|
||||
assert.True(katautils.FileExists(dirPath))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMainUserWantsUsage(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
@ -525,7 +259,7 @@ func TestMainBeforeSubCommands(t *testing.T) {
|
||||
func TestMainBeforeSubCommandsInvalidLogFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
@ -548,7 +282,7 @@ func TestMainBeforeSubCommandsInvalidLogFile(t *testing.T) {
|
||||
func TestMainBeforeSubCommandsInvalidLogFormat(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
@ -577,7 +311,7 @@ func TestMainBeforeSubCommandsInvalidLogFormat(t *testing.T) {
|
||||
func TestMainBeforeSubCommandsLoadConfigurationFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
@ -612,7 +346,7 @@ func TestMainBeforeSubCommandsLoadConfigurationFail(t *testing.T) {
|
||||
func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
@ -676,7 +410,7 @@ func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) {
|
||||
func TestMainFatal(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir(testDir, "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
@ -900,7 +634,7 @@ func TestMainCreateRuntime(t *testing.T) {
|
||||
func TestMainVersionPrinter(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
tmpdir, err := ioutil.TempDir("", "katatest")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
dir, err := ioutil.TempDir(testDir, "")
|
||||
dir, err := ioutil.TempDir("", "katatest")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
@ -23,7 +22,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
@ -52,21 +50,12 @@ func TestCreateSandboxSuccess(t *testing.T) {
|
||||
testingImpl.CreateSandboxFunc = nil
|
||||
}()
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
// defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -82,7 +71,7 @@ func TestCreateSandboxSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
// Rewrite the file
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
s := &service{
|
||||
@ -110,25 +99,16 @@ func TestCreateSandboxFail(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
s := &service{
|
||||
@ -157,21 +137,12 @@ func TestCreateSandboxConfigFail(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -216,21 +187,12 @@ func TestCreateContainerSuccess(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -240,7 +202,7 @@ func TestCreateContainerSuccess(t *testing.T) {
|
||||
spec.Annotations[testSandboxIDAnnotation] = testSandboxID
|
||||
|
||||
// rewrite file
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
s := &service{
|
||||
@ -265,21 +227,12 @@ func TestCreateContainerSuccess(t *testing.T) {
|
||||
func TestCreateContainerFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -287,7 +240,7 @@ func TestCreateContainerFail(t *testing.T) {
|
||||
spec.Annotations[testContainerTypeAnnotation] = testContainerTypeContainer
|
||||
spec.Annotations[testSandboxIDAnnotation] = testSandboxID
|
||||
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
// doesn't create sandbox first
|
||||
@ -325,21 +278,12 @@ func TestCreateContainerConfigFail(t *testing.T) {
|
||||
sandbox.CreateContainerFunc = nil
|
||||
}()
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(katautils.FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -348,7 +292,7 @@ func TestCreateContainerConfigFail(t *testing.T) {
|
||||
spec.Annotations[testContainerTypeAnnotation] = "errorType"
|
||||
spec.Annotations[testSandboxIDAnnotation] = testSandboxID
|
||||
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
s := &service{
|
||||
|
@ -7,14 +7,13 @@
|
||||
package containerdshim
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
taskAPI "github.com/containerd/containerd/runtime/v2/task"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock"
|
||||
)
|
||||
@ -26,7 +25,7 @@ func TestDeleteContainerSuccessAndFail(t *testing.T) {
|
||||
MockID: testSandboxID,
|
||||
}
|
||||
|
||||
rootPath, bundlePath := testConfigSetup(t)
|
||||
rootPath, bundlePath, _ := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(rootPath)
|
||||
_, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
@ -43,19 +42,3 @@ func TestDeleteContainerSuccessAndFail(t *testing.T) {
|
||||
s.containers[testContainerID], err = newContainer(s, reqCreate, "", nil, true)
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
func testConfigSetup(t *testing.T) (rootPath string, bundlePath string) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath = filepath.Join(tmpdir, "bundle")
|
||||
err = os.MkdirAll(bundlePath, testDirMode)
|
||||
assert.NoError(err)
|
||||
|
||||
err = createOCIConfig(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
return tmpdir, bundlePath
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ package containerdshim
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -43,13 +41,9 @@ func TestServiceCreate(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, _ := ioutil.TempDir("", "")
|
||||
tmpdir, bundleDir, _ := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundleDir := filepath.Join(tmpdir, "bundle")
|
||||
err := makeOCIBundle(bundleDir)
|
||||
assert.NoError(err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
s, err := newService("foo")
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
@ -24,6 +25,11 @@ func TestNewTtyIOFifoReopen(t *testing.T) {
|
||||
var tty *ttyIO
|
||||
assert := assert.New(t)
|
||||
ctx := context.TODO()
|
||||
|
||||
testDir, err := ioutil.TempDir("", "kata-")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
fifoPath, err := ioutil.TempDir(testDir, "fifo-path-")
|
||||
assert.NoError(err)
|
||||
stdout := filepath.Join(fifoPath, "stdout")
|
||||
@ -100,6 +106,10 @@ func TestIoCopy(t *testing.T) {
|
||||
testBytes2 := []byte("Test2")
|
||||
testBytes3 := []byte("Test3")
|
||||
|
||||
testDir, err := ioutil.TempDir("", "kata-")
|
||||
assert.NoError(err)
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
fifoPath, err := ioutil.TempDir(testDir, "fifo-path-")
|
||||
assert.NoError(err)
|
||||
dstStdoutPath := filepath.Join(fifoPath, "dststdout")
|
||||
|
@ -7,46 +7,28 @@
|
||||
package containerdshim
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
sysExec "os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// specConf is the name of the file holding the containers configuration
|
||||
specConf = "config.json"
|
||||
|
||||
TestID = "container_test"
|
||||
|
||||
testDirMode = os.FileMode(0750)
|
||||
testFileMode = os.FileMode(0640)
|
||||
// testExeFileMode = os.FileMode(0750)
|
||||
|
||||
// small docker image used to create root filesystems from
|
||||
testDockerImage = "busybox"
|
||||
|
||||
testSandboxID = "777-77-77777777"
|
||||
testContainerID = "42"
|
||||
testBundle = "bundle"
|
||||
testConsole = "/dev/pts/888"
|
||||
|
||||
testContainerTypeAnnotation = "io.kubernetes.cri.container-type"
|
||||
@ -57,10 +39,7 @@ const (
|
||||
|
||||
var (
|
||||
// package variables set by calling TestMain()
|
||||
testDir = ""
|
||||
testBundleDir = ""
|
||||
tc ktu.TestConstraint
|
||||
ctrEngine = katautils.CtrEngine{}
|
||||
)
|
||||
|
||||
// testingImpl is a concrete mock RVC implementation used for testing
|
||||
@ -73,57 +52,6 @@ func init() {
|
||||
fmt.Printf("INFO: switching to fake virtcontainers implementation for testing\n")
|
||||
vci = testingImpl
|
||||
|
||||
var err error
|
||||
|
||||
fmt.Printf("INFO: creating test directory\n")
|
||||
testDir, err = ioutil.TempDir("", "shimV2-")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create test directory: %v", err))
|
||||
}
|
||||
fmt.Printf("INFO: test directory is %v\n", testDir)
|
||||
|
||||
var output string
|
||||
for _, name := range katautils.DockerLikeCtrEngines {
|
||||
fmt.Printf("INFO: checking for container engine: %s\n", name)
|
||||
|
||||
output, err = ctrEngine.Init(name)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ctrEngine.Name == "" {
|
||||
panic(fmt.Sprintf("ERROR: Docker-like container engine not accessible to current user: %v (error %v)",
|
||||
output, err))
|
||||
}
|
||||
|
||||
// Do this now to avoid hitting the test timeout value due to
|
||||
// slow network response.
|
||||
fmt.Printf("INFO: ensuring required container image (%v) is available\n", testDockerImage)
|
||||
// Only hit the network if the image doesn't exist locally
|
||||
_, err = ctrEngine.Inspect(testDockerImage)
|
||||
if err == nil {
|
||||
fmt.Printf("INFO: container image %v already exists locally\n", testDockerImage)
|
||||
} else {
|
||||
fmt.Printf("INFO: pulling container image %v\n", testDockerImage)
|
||||
_, err = ctrEngine.Pull(testDockerImage)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
testBundleDir = filepath.Join(testDir, testBundle)
|
||||
err = os.MkdirAll(testBundleDir, testDirMode)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create bundle directory %v: %v", testBundleDir, err))
|
||||
}
|
||||
|
||||
fmt.Printf("INFO: creating OCI bundle in %v for tests to use\n", testBundleDir)
|
||||
err = realMakeOCIBundle(testBundleDir)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create OCI bundle: %v", err))
|
||||
}
|
||||
|
||||
tc = ktu.NewTestConstraint(false)
|
||||
|
||||
// disable shim management server.
|
||||
@ -131,46 +59,6 @@ func init() {
|
||||
defaultStartManagementServerFunc = nil
|
||||
}
|
||||
|
||||
// createOCIConfig creates an OCI configuration (spec) file in
|
||||
// the bundle directory specified (which must exist).
|
||||
func createOCIConfig(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !katautils.FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %s does not exist", bundleDir)
|
||||
}
|
||||
|
||||
var configCmd string
|
||||
|
||||
// Search for a suitable version of runc to use to generate
|
||||
// the OCI config file.
|
||||
for _, cmd := range []string{"docker-runc", "runc"} {
|
||||
fullPath, err := sysExec.LookPath(cmd)
|
||||
if err == nil {
|
||||
configCmd = fullPath
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if configCmd == "" {
|
||||
return errors.New("Cannot find command to generate OCI config file")
|
||||
}
|
||||
|
||||
_, err := utils.RunCommand([]string{configCmd, "spec", "--bundle", bundleDir})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specFile := filepath.Join(bundleDir, specConf)
|
||||
if !katautils.FileExists(specFile) {
|
||||
return fmt.Errorf("generated OCI config file does not exist: %v", specFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createEmptyFile(path string) (err error) {
|
||||
return ioutil.WriteFile(path, []byte(""), testFileMode)
|
||||
}
|
||||
@ -221,119 +109,6 @@ func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConf
|
||||
}, nil
|
||||
}
|
||||
|
||||
// realMakeOCIBundle will create an OCI bundle (including the "config.json"
|
||||
// config file) in the directory specified (which must already exist).
|
||||
//
|
||||
// XXX: Note that tests should *NOT* call this function - they should
|
||||
// XXX: instead call makeOCIBundle().
|
||||
func realMakeOCIBundle(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !katautils.FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %v does not exist", bundleDir)
|
||||
}
|
||||
|
||||
err := createOCIConfig(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note the unusual parameter (a directory, not the config
|
||||
// file to parse!)
|
||||
spec, err := compatoci.ParseConfigJSON(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the rootfs directory name the OCI config refers to
|
||||
ociRootPath := spec.Root.Path
|
||||
|
||||
rootfsDir := filepath.Join(bundleDir, ociRootPath)
|
||||
|
||||
if strings.HasPrefix(ociRootPath, "/") {
|
||||
return fmt.Errorf("Cannot handle absolute rootfs as bundle must be unique to each test")
|
||||
}
|
||||
|
||||
err = createRootfs(rootfsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create an OCI bundle in the specified directory.
|
||||
//
|
||||
// Note that the directory will be created, but it's parent is expected to exist.
|
||||
//
|
||||
// This function works by copying the already-created test bundle. Ideally,
|
||||
// the bundle would be recreated for each test, but createRootfs() uses
|
||||
// docker which on some systems is too slow, resulting in the tests timing
|
||||
// out.
|
||||
func makeOCIBundle(bundleDir string) error {
|
||||
from := testBundleDir
|
||||
to := bundleDir
|
||||
|
||||
// only the basename of bundleDir needs to exist as bundleDir
|
||||
// will get created by cp(1).
|
||||
base := filepath.Dir(bundleDir)
|
||||
|
||||
for _, dir := range []string{from, base} {
|
||||
if !katautils.FileExists(dir) {
|
||||
return fmt.Errorf("BUG: directory %v should exist", dir)
|
||||
}
|
||||
}
|
||||
|
||||
output, err := utils.RunCommandFull([]string{"cp", "-a", from, to}, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to copy test OCI bundle from %v to %v: %v (output: %v)", from, to, err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createRootfs creates a minimal root filesystem below the specified
|
||||
// directory.
|
||||
func createRootfs(dir string) error {
|
||||
err := os.MkdirAll(dir, testDirMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := ctrEngine.Create(testDockerImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctrEngine.GetRootfs(container, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = ctrEngine.Rm(container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeOCIConfigFile(spec specs.Spec, configPath string) error {
|
||||
if configPath == "" {
|
||||
return errors.New("BUG: need config file path")
|
||||
}
|
||||
|
||||
bytes, err := json.MarshalIndent(spec, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(configPath, bytes, testFileMode)
|
||||
}
|
||||
|
||||
func TestNoNeedForOutput(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
testFileMode = os.FileMode(0640)
|
||||
invalidOperator = 1234
|
||||
|
||||
skipUnknownDistroName = "skipping test as cannot determine distro name"
|
||||
|
@ -7,8 +7,203 @@
|
||||
package katatestutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
testDirMode = os.FileMode(0750)
|
||||
testFileMode = os.FileMode(0640)
|
||||
|
||||
busyboxConfigJson = `
|
||||
{
|
||||
"ociVersion": "1.0.1-dev",
|
||||
"process": {
|
||||
"terminal": true,
|
||||
"user": {
|
||||
"uid": 0,
|
||||
"gid": 0
|
||||
},
|
||||
"args": [
|
||||
"sh"
|
||||
],
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm"
|
||||
],
|
||||
"cwd": "/",
|
||||
"capabilities": {
|
||||
"bounding": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"effective": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"inheritable": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"permitted": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
],
|
||||
"ambient": [
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
]
|
||||
},
|
||||
"rlimits": [
|
||||
{
|
||||
"type": "RLIMIT_NOFILE",
|
||||
"hard": 1024,
|
||||
"soft": 1024
|
||||
}
|
||||
],
|
||||
"noNewPrivileges": true
|
||||
},
|
||||
"root": {
|
||||
"path": "rootfs",
|
||||
"readonly": true
|
||||
},
|
||||
"hostname": "runc",
|
||||
"mounts": [
|
||||
{
|
||||
"destination": "/proc",
|
||||
"type": "proc",
|
||||
"source": "proc"
|
||||
},
|
||||
{
|
||||
"destination": "/dev",
|
||||
"type": "tmpfs",
|
||||
"source": "tmpfs",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"strictatime",
|
||||
"mode=755",
|
||||
"size=65536k"
|
||||
]
|
||||
},
|
||||
{
|
||||
"destination": "/dev/pts",
|
||||
"type": "devpts",
|
||||
"source": "devpts",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"newinstance",
|
||||
"ptmxmode=0666",
|
||||
"mode=0620",
|
||||
"gid=5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"destination": "/dev/shm",
|
||||
"type": "tmpfs",
|
||||
"source": "shm",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"mode=1777",
|
||||
"size=65536k"
|
||||
]
|
||||
},
|
||||
{
|
||||
"destination": "/dev/mqueue",
|
||||
"type": "mqueue",
|
||||
"source": "mqueue",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"destination": "/sys",
|
||||
"type": "sysfs",
|
||||
"source": "sysfs",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"ro"
|
||||
]
|
||||
},
|
||||
{
|
||||
"destination": "/sys/fs/cgroup",
|
||||
"type": "cgroup",
|
||||
"source": "cgroup",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"relatime",
|
||||
"ro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"linux": {
|
||||
"resources": {
|
||||
"devices": [
|
||||
{
|
||||
"allow": false,
|
||||
"access": "rwm"
|
||||
}
|
||||
]
|
||||
},
|
||||
"namespaces": [
|
||||
{
|
||||
"type": "pid"
|
||||
},
|
||||
{
|
||||
"type": "network"
|
||||
},
|
||||
{
|
||||
"type": "ipc"
|
||||
},
|
||||
{
|
||||
"type": "uts"
|
||||
},
|
||||
{
|
||||
"type": "mount"
|
||||
}
|
||||
],
|
||||
"maskedPaths": [
|
||||
"/proc/acpi",
|
||||
"/proc/asound",
|
||||
"/proc/kcore",
|
||||
"/proc/keys",
|
||||
"/proc/latency_stats",
|
||||
"/proc/timer_list",
|
||||
"/proc/timer_stats",
|
||||
"/proc/sched_debug",
|
||||
"/sys/firmware",
|
||||
"/proc/scsi"
|
||||
],
|
||||
"readonlyPaths": [
|
||||
"/proc/bus",
|
||||
"/proc/fs",
|
||||
"/proc/irq",
|
||||
"/proc/sys",
|
||||
"/proc/sysrq-trigger"
|
||||
]
|
||||
}
|
||||
}`
|
||||
)
|
||||
|
||||
type RuntimeConfigOptions struct {
|
||||
@ -154,3 +349,34 @@ func IsInGitHubActions() bool {
|
||||
// https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables
|
||||
return os.Getenv("GITHUB_ACTIONS") == "true"
|
||||
}
|
||||
|
||||
func SetupOCIConfigFile(t *testing.T) (rootPath string, bundlePath, ociConfigFile string) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "katatest-")
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath = filepath.Join(tmpdir, "bundle")
|
||||
err = os.MkdirAll(bundlePath, testDirMode)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile = filepath.Join(bundlePath, "config.json")
|
||||
err = ioutil.WriteFile(ociConfigFile, []byte(busyboxConfigJson), testFileMode)
|
||||
assert.NoError(err)
|
||||
|
||||
return tmpdir, bundlePath, ociConfigFile
|
||||
}
|
||||
|
||||
// WriteOCIConfigFile using spec to update OCI config file by path configPath
|
||||
func WriteOCIConfigFile(spec specs.Spec, configPath string) error {
|
||||
if configPath == "" {
|
||||
return errors.New("BUG: need config file path")
|
||||
}
|
||||
|
||||
bytes, err := json.MarshalIndent(spec, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(configPath, bytes, testFileMode)
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
// Copyright (c) 2019 SUSE LLC
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||
)
|
||||
|
||||
type CtrEngine struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
var (
|
||||
DockerLikeCtrEngines = []string{"docker", "podman"}
|
||||
)
|
||||
|
||||
func (e *CtrEngine) Init(name string) (string, error) {
|
||||
var out string
|
||||
out, err := utils.RunCommandFull([]string{name, "version"}, true)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
e.Name = name
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (e *CtrEngine) Inspect(image string) (string, error) {
|
||||
// Only hit the network if the image doesn't exist locally
|
||||
return utils.RunCommand([]string{e.Name, "inspect", "--type=image", image})
|
||||
}
|
||||
|
||||
func (e *CtrEngine) Pull(image string) (string, error) {
|
||||
return utils.RunCommand([]string{e.Name, "pull", image})
|
||||
}
|
||||
|
||||
func (e *CtrEngine) Create(image string) (string, error) {
|
||||
return utils.RunCommand([]string{e.Name, "create", image})
|
||||
}
|
||||
|
||||
func (e *CtrEngine) Rm(ctrID string) (string, error) {
|
||||
return utils.RunCommand([]string{e.Name, "rm", ctrID})
|
||||
}
|
||||
|
||||
func (e *CtrEngine) GetRootfs(ctrID string, dir string) error {
|
||||
cmd1 := exec.Command(e.Name, "export", ctrID)
|
||||
cmd2 := exec.Command("tar", "-C", dir, "-xvf", "-")
|
||||
|
||||
cmd1Stdout, err := cmd1.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd2.Stdin = cmd1Stdout
|
||||
|
||||
err = cmd2.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cmd1.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cmd2.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -8,7 +8,6 @@ package katautils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -20,7 +19,6 @@ import (
|
||||
"testing"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci"
|
||||
@ -37,8 +35,6 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
testBundleDir = ""
|
||||
|
||||
// testingImpl is a concrete mock RVC implementation used for testing
|
||||
testingImpl = &vcmock.VCMock{}
|
||||
// mock sandbox
|
||||
@ -53,49 +49,6 @@ func init() {
|
||||
tc = ktu.NewTestConstraint(false)
|
||||
}
|
||||
|
||||
func writeOCIConfigFile(spec specs.Spec, configPath string) error {
|
||||
if configPath == "" {
|
||||
return errors.New("BUG: need config file path")
|
||||
}
|
||||
|
||||
bytes, err := json.MarshalIndent(spec, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(configPath, bytes, testFileMode)
|
||||
}
|
||||
|
||||
// Create an OCI bundle in the specified directory.
|
||||
//
|
||||
// Note that the directory will be created, but it's parent is expected to exist.
|
||||
//
|
||||
// This function works by copying the already-created test bundle. Ideally,
|
||||
// the bundle would be recreated for each test, but createRootfs() uses
|
||||
// docker which on some systems is too slow, resulting in the tests timing
|
||||
// out.
|
||||
func makeOCIBundle(bundleDir string) error {
|
||||
from := testBundleDir
|
||||
to := bundleDir
|
||||
|
||||
// only the basename of bundleDir needs to exist as bundleDir
|
||||
// will get created by cp(1).
|
||||
base := filepath.Dir(bundleDir)
|
||||
|
||||
for _, dir := range []string{from, base} {
|
||||
if !FileExists(dir) {
|
||||
return fmt.Errorf("BUG: directory %v should exist", dir)
|
||||
}
|
||||
}
|
||||
|
||||
output, err := utils.RunCommandFull([]string{"cp", "-a", from, to}, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to copy test OCI bundle from %v to %v: %v (output: %v)", from, to, err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// newTestRuntimeConfig creates a new RuntimeConfig
|
||||
func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConfig, error) {
|
||||
if dir == "" {
|
||||
@ -262,21 +215,12 @@ func TestSetKernelParamsUserOptionTakesPriority(t *testing.T) {
|
||||
func TestCreateSandboxConfigFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -305,21 +249,12 @@ func TestCreateSandboxFail(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
|
||||
assert.NoError(err)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -375,18 +310,9 @@ func TestCheckForFips(t *testing.T) {
|
||||
func TestCreateContainerContainerConfigFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -396,7 +322,7 @@ func TestCreateContainerContainerConfigFail(t *testing.T) {
|
||||
spec.Annotations[testContainerTypeAnnotation] = containerType
|
||||
|
||||
// rewrite file
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
rootFs := vc.RootFs{Mounted: true}
|
||||
@ -412,18 +338,9 @@ func TestCreateContainerContainerConfigFail(t *testing.T) {
|
||||
func TestCreateContainerFail(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -433,7 +350,7 @@ func TestCreateContainerFail(t *testing.T) {
|
||||
spec.Annotations[testSandboxIDAnnotation] = testSandboxID
|
||||
|
||||
// rewrite file
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
rootFs := vc.RootFs{Mounted: true}
|
||||
@ -456,18 +373,9 @@ func TestCreateContainer(t *testing.T) {
|
||||
mockSandbox.CreateContainerFunc = nil
|
||||
}()
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
assert.NoError(err)
|
||||
tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
bundlePath := filepath.Join(tmpdir, "bundle")
|
||||
|
||||
err = makeOCIBundle(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
ociConfigFile := filepath.Join(bundlePath, "config.json")
|
||||
assert.True(FileExists(ociConfigFile))
|
||||
|
||||
spec, err := compatoci.ParseConfigJSON(bundlePath)
|
||||
assert.NoError(err)
|
||||
|
||||
@ -477,7 +385,7 @@ func TestCreateContainer(t *testing.T) {
|
||||
spec.Annotations[testSandboxIDAnnotation] = testSandboxID
|
||||
|
||||
// rewrite file
|
||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||
err = ktu.WriteOCIConfigFile(spec, ociConfigFile)
|
||||
assert.NoError(err)
|
||||
|
||||
rootFs := vc.RootFs{Mounted: true}
|
||||
|
@ -7,20 +7,15 @@
|
||||
package katautils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -28,173 +23,14 @@ const (
|
||||
testDirMode = os.FileMode(0750)
|
||||
testFileMode = os.FileMode(0640)
|
||||
|
||||
// small docker image used to create root filesystems from
|
||||
testDockerImage = "busybox"
|
||||
|
||||
testSandboxID = "99999999-9999-9999-99999999999999999"
|
||||
testContainerID = "1"
|
||||
testBundle = "bundle"
|
||||
specConfig = "config.json"
|
||||
)
|
||||
|
||||
var (
|
||||
testDir = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
fmt.Printf("INFO: creating test directory\n")
|
||||
testDir, err = ioutil.TempDir("", fmt.Sprintf("%s-", NAME))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create test directory: %v", err))
|
||||
}
|
||||
|
||||
fmt.Printf("INFO: test directory is %v\n", testDir)
|
||||
|
||||
testBundleDir = filepath.Join(testDir, testBundle)
|
||||
err = os.MkdirAll(testBundleDir, testDirMode)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create bundle directory %v: %v", testBundleDir, err))
|
||||
}
|
||||
|
||||
fmt.Printf("INFO: creating OCI bundle in %v for tests to use\n", testBundleDir)
|
||||
err = realMakeOCIBundle(testBundleDir)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ERROR: failed to create OCI bundle: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// createOCIConfig creates an OCI configuration (spec) file in
|
||||
// the bundle directory specified (which must exist).
|
||||
func createOCIConfig(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %s does not exist", bundleDir)
|
||||
}
|
||||
|
||||
var configCmd string
|
||||
|
||||
// Search for a suitable version of runc to use to generate
|
||||
// the OCI config file.
|
||||
for _, cmd := range []string{"docker-runc", "runc"} {
|
||||
fullPath, err := exec.LookPath(cmd)
|
||||
if err == nil {
|
||||
configCmd = fullPath
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if configCmd == "" {
|
||||
return errors.New("Cannot find command to generate OCI config file")
|
||||
}
|
||||
|
||||
_, err := utils.RunCommand([]string{configCmd, "spec", "--bundle", bundleDir})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specFile := filepath.Join(bundleDir, specConfig)
|
||||
if !FileExists(specFile) {
|
||||
return fmt.Errorf("generated OCI config file does not exist: %v", specFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// realMakeOCIBundle will create an OCI bundle (including the "config.json"
|
||||
// config file) in the directory specified (which must already exist).
|
||||
//
|
||||
// XXX: Note that tests should *NOT* call this function - they should
|
||||
// XXX: instead call makeOCIBundle().
|
||||
func realMakeOCIBundle(bundleDir string) error {
|
||||
if bundleDir == "" {
|
||||
return errors.New("BUG: Need bundle directory")
|
||||
}
|
||||
|
||||
if !FileExists(bundleDir) {
|
||||
return fmt.Errorf("BUG: Bundle directory %v does not exist", bundleDir)
|
||||
}
|
||||
|
||||
err := createOCIConfig(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Note the unusual parameter (a directory, not the config
|
||||
// file to parse!)
|
||||
spec, err := compatoci.ParseConfigJSON(bundleDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the rootfs directory name the OCI config refers to
|
||||
ociRootPath := spec.Root.Path
|
||||
|
||||
rootfsDir := filepath.Join(bundleDir, ociRootPath)
|
||||
|
||||
if strings.HasPrefix(ociRootPath, "/") {
|
||||
return fmt.Errorf("Cannot handle absolute rootfs as bundle must be unique to each test")
|
||||
}
|
||||
|
||||
err = createRootfs(rootfsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createRootfs creates a minimal root filesystem below the specified
|
||||
// directory.
|
||||
func createRootfs(dir string) error {
|
||||
var (
|
||||
output string
|
||||
err error
|
||||
)
|
||||
|
||||
ctrEngine := CtrEngine{}
|
||||
for _, name := range DockerLikeCtrEngines {
|
||||
fmt.Printf("INFO: checking for container engine: %s\n", name)
|
||||
|
||||
output, err = ctrEngine.Init(name)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ctrEngine.Name == "" {
|
||||
panic(fmt.Sprintf("ERROR: Docker-like container engine not accessible to current user: %v (error %v)",
|
||||
output, err))
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dir, testDirMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := ctrEngine.Create(testDockerImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctrEngine.GetRootfs(container, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = ctrEngine.Rm(container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFile(file, contents string) error {
|
||||
return ioutil.WriteFile(file, []byte(contents), testFileMode)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user