mirror of
				https://github.com/kata-containers/kata-containers.git
				synced 2025-10-31 17:37:20 +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:
		| @@ -30,9 +30,6 @@ import ( | |||||||
| 	"github.com/urfave/cli" | 	"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 | // arch is the architecture for the running program | ||||||
| const arch = goruntime.GOARCH | const arch = goruntime.GOARCH | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" |  | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| @@ -22,9 +21,7 @@ import ( | |||||||
|  |  | ||||||
| 	ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" | 	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/katautils" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/pkg/utils" |  | ||||||
| 	vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers" | 	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/oci" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | ||||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||||
| @@ -38,19 +35,12 @@ const ( | |||||||
| 	testFileMode    = os.FileMode(0640) | 	testFileMode    = os.FileMode(0640) | ||||||
| 	testExeFileMode = os.FileMode(0750) | 	testExeFileMode = os.FileMode(0750) | ||||||
|  |  | ||||||
| 	// small docker image used to create root filesystems from |  | ||||||
| 	testDockerImage = "busybox" |  | ||||||
|  |  | ||||||
| 	testBundle  = "bundle" |  | ||||||
| 	testConsole = "/dev/pts/999" | 	testConsole = "/dev/pts/999" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	// package variables set by calling TestMain() | 	// package variables set by calling TestMain() | ||||||
| 	testDir       = "" | 	tc ktu.TestConstraint | ||||||
| 	testBundleDir = "" |  | ||||||
| 	tc            ktu.TestConstraint |  | ||||||
| 	ctrEngine     = katautils.CtrEngine{} |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // testingImpl is a concrete mock RVC implementation used for testing | // 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") | 	fmt.Printf("INFO: switching to fake virtcontainers implementation for testing\n") | ||||||
| 	vci = testingImpl | 	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) | 	tc = ktu.NewTestConstraint(false) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -143,8 +82,6 @@ func resetCLIGlobals() { | |||||||
| func runUnitTests(m *testing.M) { | func runUnitTests(m *testing.M) { | ||||||
| 	ret := m.Run() | 	ret := m.Run() | ||||||
|  |  | ||||||
| 	os.RemoveAll(testDir) |  | ||||||
|  |  | ||||||
| 	os.Exit(ret) | 	os.Exit(ret) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -232,146 +169,6 @@ func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConf | |||||||
| 	}, nil | 	}, 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 { | func createCLIContextWithApp(flagSet *flag.FlagSet, app *cli.App) *cli.Context { | ||||||
| 	ctx := cli.NewContext(app, flagSet, nil) | 	ctx := cli.NewContext(app, flagSet, nil) | ||||||
|  |  | ||||||
| @@ -390,69 +187,6 @@ func createCLIContext(flagset *flag.FlagSet) *cli.Context { | |||||||
| 	return createCLIContextWithApp(flagset, cli.NewApp()) | 	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) { | func TestMainUserWantsUsage(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| @@ -525,7 +259,7 @@ func TestMainBeforeSubCommands(t *testing.T) { | |||||||
| func TestMainBeforeSubCommandsInvalidLogFile(t *testing.T) { | func TestMainBeforeSubCommandsInvalidLogFile(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir(testDir, "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| @@ -548,7 +282,7 @@ func TestMainBeforeSubCommandsInvalidLogFile(t *testing.T) { | |||||||
| func TestMainBeforeSubCommandsInvalidLogFormat(t *testing.T) { | func TestMainBeforeSubCommandsInvalidLogFormat(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir(testDir, "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| @@ -577,7 +311,7 @@ func TestMainBeforeSubCommandsInvalidLogFormat(t *testing.T) { | |||||||
| func TestMainBeforeSubCommandsLoadConfigurationFail(t *testing.T) { | func TestMainBeforeSubCommandsLoadConfigurationFail(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir(testDir, "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| @@ -612,7 +346,7 @@ func TestMainBeforeSubCommandsLoadConfigurationFail(t *testing.T) { | |||||||
| func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) { | func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir(testDir, "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| @@ -676,7 +410,7 @@ func TestMainBeforeSubCommandsShowCCConfigPaths(t *testing.T) { | |||||||
| func TestMainFatal(t *testing.T) { | func TestMainFatal(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir(testDir, "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| @@ -900,7 +634,7 @@ func TestMainCreateRuntime(t *testing.T) { | |||||||
| func TestMainVersionPrinter(t *testing.T) { | func TestMainVersionPrinter(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, err := ioutil.TempDir("", "katatest") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestFileExists(t *testing.T) { | func TestFileExists(t *testing.T) { | ||||||
| 	dir, err := ioutil.TempDir(testDir, "") | 	dir, err := ioutil.TempDir("", "katatest") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" |  | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/containerd/containerd/namespaces" | 	"github.com/containerd/containerd/namespaces" | ||||||
| @@ -23,7 +22,6 @@ import ( | |||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  |  | ||||||
| 	ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" | 	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" | 	vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers" | ||||||
| 	vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations" | 	vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci" | 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/compatoci" | ||||||
| @@ -52,21 +50,12 @@ func TestCreateSandboxSuccess(t *testing.T) { | |||||||
| 		testingImpl.CreateSandboxFunc = nil | 		testingImpl.CreateSandboxFunc = nil | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) | 	// defer os.RemoveAll(tmpdir) | ||||||
| 	defer os.RemoveAll(tmpdir) |  | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -82,7 +71,7 @@ func TestCreateSandboxSuccess(t *testing.T) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Rewrite the file | 	// Rewrite the file | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	s := &service{ | 	s := &service{ | ||||||
| @@ -110,25 +99,16 @@ func TestCreateSandboxFail(t *testing.T) { | |||||||
|  |  | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	s := &service{ | 	s := &service{ | ||||||
| @@ -157,21 +137,12 @@ func TestCreateSandboxConfigFail(t *testing.T) { | |||||||
|  |  | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -216,21 +187,12 @@ func TestCreateContainerSuccess(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -240,7 +202,7 @@ func TestCreateContainerSuccess(t *testing.T) { | |||||||
| 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | ||||||
|  |  | ||||||
| 	// rewrite file | 	// rewrite file | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	s := &service{ | 	s := &service{ | ||||||
| @@ -265,21 +227,12 @@ func TestCreateContainerSuccess(t *testing.T) { | |||||||
| func TestCreateContainerFail(t *testing.T) { | func TestCreateContainerFail(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -287,7 +240,7 @@ func TestCreateContainerFail(t *testing.T) { | |||||||
| 	spec.Annotations[testContainerTypeAnnotation] = testContainerTypeContainer | 	spec.Annotations[testContainerTypeAnnotation] = testContainerTypeContainer | ||||||
| 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | ||||||
|  |  | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	// doesn't create sandbox first | 	// doesn't create sandbox first | ||||||
| @@ -325,21 +278,12 @@ func TestCreateContainerConfigFail(t *testing.T) { | |||||||
| 		sandbox.CreateContainerFunc = nil | 		sandbox.CreateContainerFunc = nil | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -348,7 +292,7 @@ func TestCreateContainerConfigFail(t *testing.T) { | |||||||
| 	spec.Annotations[testContainerTypeAnnotation] = "errorType" | 	spec.Annotations[testContainerTypeAnnotation] = "errorType" | ||||||
| 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | ||||||
|  |  | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	s := &service{ | 	s := &service{ | ||||||
|   | |||||||
| @@ -7,14 +7,13 @@ | |||||||
| package containerdshim | package containerdshim | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"io/ioutil" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" |  | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	taskAPI "github.com/containerd/containerd/runtime/v2/task" | 	taskAPI "github.com/containerd/containerd/runtime/v2/task" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"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/compatoci" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | ||||||
| ) | ) | ||||||
| @@ -26,7 +25,7 @@ func TestDeleteContainerSuccessAndFail(t *testing.T) { | |||||||
| 		MockID: testSandboxID, | 		MockID: testSandboxID, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	rootPath, bundlePath := testConfigSetup(t) | 	rootPath, bundlePath, _ := ktu.SetupOCIConfigFile(t) | ||||||
| 	defer os.RemoveAll(rootPath) | 	defer os.RemoveAll(rootPath) | ||||||
| 	_, err := compatoci.ParseConfigJSON(bundlePath) | 	_, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| @@ -43,19 +42,3 @@ func TestDeleteContainerSuccessAndFail(t *testing.T) { | |||||||
| 	s.containers[testContainerID], err = newContainer(s, reqCreate, "", nil, true) | 	s.containers[testContainerID], err = newContainer(s, reqCreate, "", nil, true) | ||||||
| 	assert.NoError(err) | 	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 ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| @@ -43,13 +41,9 @@ func TestServiceCreate(t *testing.T) { | |||||||
|  |  | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, _ := ioutil.TempDir("", "") | 	tmpdir, bundleDir, _ := ktu.SetupOCIConfigFile(t) | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	bundleDir := filepath.Join(tmpdir, "bundle") |  | ||||||
| 	err := makeOCIBundle(bundleDir) |  | ||||||
| 	assert.NoError(err) |  | ||||||
|  |  | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
|  |  | ||||||
| 	s, err := newService("foo") | 	s, err := newService("foo") | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"io" | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -24,6 +25,11 @@ func TestNewTtyIOFifoReopen(t *testing.T) { | |||||||
| 	var tty *ttyIO | 	var tty *ttyIO | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
| 	ctx := context.TODO() | 	ctx := context.TODO() | ||||||
|  |  | ||||||
|  | 	testDir, err := ioutil.TempDir("", "kata-") | ||||||
|  | 	assert.NoError(err) | ||||||
|  | 	defer os.RemoveAll(testDir) | ||||||
|  |  | ||||||
| 	fifoPath, err := ioutil.TempDir(testDir, "fifo-path-") | 	fifoPath, err := ioutil.TempDir(testDir, "fifo-path-") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	stdout := filepath.Join(fifoPath, "stdout") | 	stdout := filepath.Join(fifoPath, "stdout") | ||||||
| @@ -100,6 +106,10 @@ func TestIoCopy(t *testing.T) { | |||||||
| 	testBytes2 := []byte("Test2") | 	testBytes2 := []byte("Test2") | ||||||
| 	testBytes3 := []byte("Test3") | 	testBytes3 := []byte("Test3") | ||||||
|  |  | ||||||
|  | 	testDir, err := ioutil.TempDir("", "kata-") | ||||||
|  | 	assert.NoError(err) | ||||||
|  | 	defer os.RemoveAll(testDir) | ||||||
|  |  | ||||||
| 	fifoPath, err := ioutil.TempDir(testDir, "fifo-path-") | 	fifoPath, err := ioutil.TempDir(testDir, "fifo-path-") | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
| 	dstStdoutPath := filepath.Join(fifoPath, "dststdout") | 	dstStdoutPath := filepath.Join(fifoPath, "dststdout") | ||||||
|   | |||||||
| @@ -7,46 +7,28 @@ | |||||||
| package containerdshim | package containerdshim | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	sysExec "os/exec" |  | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" |  | ||||||
| 	"strings" |  | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  |  | ||||||
| 	"github.com/opencontainers/runtime-spec/specs-go" |  | ||||||
|  |  | ||||||
| 	ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" | 	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" | 	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/oci" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/vcmock" | ||||||
|  | 	"github.com/pkg/errors" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	// specConf is the name of the file holding the containers configuration |  | ||||||
| 	specConf = "config.json" |  | ||||||
|  |  | ||||||
| 	TestID = "container_test" | 	TestID = "container_test" | ||||||
|  |  | ||||||
| 	testDirMode  = os.FileMode(0750) |  | ||||||
| 	testFileMode = os.FileMode(0640) | 	testFileMode = os.FileMode(0640) | ||||||
| 	// testExeFileMode         = os.FileMode(0750) |  | ||||||
|  |  | ||||||
| 	// small docker image used to create root filesystems from |  | ||||||
| 	testDockerImage = "busybox" |  | ||||||
|  |  | ||||||
| 	testSandboxID   = "777-77-77777777" | 	testSandboxID   = "777-77-77777777" | ||||||
| 	testContainerID = "42" | 	testContainerID = "42" | ||||||
| 	testBundle      = "bundle" |  | ||||||
| 	testConsole     = "/dev/pts/888" | 	testConsole     = "/dev/pts/888" | ||||||
|  |  | ||||||
| 	testContainerTypeAnnotation = "io.kubernetes.cri.container-type" | 	testContainerTypeAnnotation = "io.kubernetes.cri.container-type" | ||||||
| @@ -57,10 +39,7 @@ const ( | |||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	// package variables set by calling TestMain() | 	// package variables set by calling TestMain() | ||||||
| 	testDir       = "" | 	tc ktu.TestConstraint | ||||||
| 	testBundleDir = "" |  | ||||||
| 	tc            ktu.TestConstraint |  | ||||||
| 	ctrEngine     = katautils.CtrEngine{} |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // testingImpl is a concrete mock RVC implementation used for testing | // 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") | 	fmt.Printf("INFO: switching to fake virtcontainers implementation for testing\n") | ||||||
| 	vci = testingImpl | 	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) | 	tc = ktu.NewTestConstraint(false) | ||||||
|  |  | ||||||
| 	// disable shim management server. | 	// disable shim management server. | ||||||
| @@ -131,46 +59,6 @@ func init() { | |||||||
| 	defaultStartManagementServerFunc = nil | 	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) { | func createEmptyFile(path string) (err error) { | ||||||
| 	return ioutil.WriteFile(path, []byte(""), testFileMode) | 	return ioutil.WriteFile(path, []byte(""), testFileMode) | ||||||
| } | } | ||||||
| @@ -221,119 +109,6 @@ func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConf | |||||||
| 	}, nil | 	}, 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) { | func TestNoNeedForOutput(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	testFileMode    = os.FileMode(0640) |  | ||||||
| 	invalidOperator = 1234 | 	invalidOperator = 1234 | ||||||
|  |  | ||||||
| 	skipUnknownDistroName = "skipping test as cannot determine distro name" | 	skipUnknownDistroName = "skipping test as cannot determine distro name" | ||||||
|   | |||||||
| @@ -7,8 +7,203 @@ | |||||||
| package katatestutils | package katatestutils | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"errors" | ||||||
|  | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
| 	"strconv" | 	"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 { | type RuntimeConfigOptions struct { | ||||||
| @@ -154,3 +349,34 @@ func IsInGitHubActions() bool { | |||||||
| 	// https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables | 	// https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables | ||||||
| 	return os.Getenv("GITHUB_ACTIONS") == "true" | 	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 ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| @@ -20,7 +19,6 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" | 	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" | 	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/compatoci" | ||||||
| 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci" | 	"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci" | ||||||
| @@ -37,8 +35,6 @@ const ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	testBundleDir = "" |  | ||||||
|  |  | ||||||
| 	// testingImpl is a concrete mock RVC implementation used for testing | 	// testingImpl is a concrete mock RVC implementation used for testing | ||||||
| 	testingImpl = &vcmock.VCMock{} | 	testingImpl = &vcmock.VCMock{} | ||||||
| 	// mock sandbox | 	// mock sandbox | ||||||
| @@ -53,49 +49,6 @@ func init() { | |||||||
| 	tc = ktu.NewTestConstraint(false) | 	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 | // newTestRuntimeConfig creates a new RuntimeConfig | ||||||
| func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConfig, error) { | func newTestRuntimeConfig(dir, consolePath string, create bool) (oci.RuntimeConfig, error) { | ||||||
| 	if dir == "" { | 	if dir == "" { | ||||||
| @@ -262,21 +215,12 @@ func TestSetKernelParamsUserOptionTakesPriority(t *testing.T) { | |||||||
| func TestCreateSandboxConfigFail(t *testing.T) { | func TestCreateSandboxConfigFail(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -305,21 +249,12 @@ func TestCreateSandboxFail(t *testing.T) { | |||||||
|  |  | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, _ := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	defer os.RemoveAll(tmpdir) | ||||||
|  |  | ||||||
| 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | 	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true) | ||||||
| 	assert.NoError(err) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -375,18 +310,9 @@ func TestCheckForFips(t *testing.T) { | |||||||
| func TestCreateContainerContainerConfigFail(t *testing.T) { | func TestCreateContainerContainerConfigFail(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -396,7 +322,7 @@ func TestCreateContainerContainerConfigFail(t *testing.T) { | |||||||
| 	spec.Annotations[testContainerTypeAnnotation] = containerType | 	spec.Annotations[testContainerTypeAnnotation] = containerType | ||||||
|  |  | ||||||
| 	// rewrite file | 	// rewrite file | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	rootFs := vc.RootFs{Mounted: true} | 	rootFs := vc.RootFs{Mounted: true} | ||||||
| @@ -412,18 +338,9 @@ func TestCreateContainerContainerConfigFail(t *testing.T) { | |||||||
| func TestCreateContainerFail(t *testing.T) { | func TestCreateContainerFail(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -433,7 +350,7 @@ func TestCreateContainerFail(t *testing.T) { | |||||||
| 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | ||||||
|  |  | ||||||
| 	// rewrite file | 	// rewrite file | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	rootFs := vc.RootFs{Mounted: true} | 	rootFs := vc.RootFs{Mounted: true} | ||||||
| @@ -456,18 +373,9 @@ func TestCreateContainer(t *testing.T) { | |||||||
| 		mockSandbox.CreateContainerFunc = nil | 		mockSandbox.CreateContainerFunc = nil | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	tmpdir, err := ioutil.TempDir("", "") | 	tmpdir, bundlePath, ociConfigFile := ktu.SetupOCIConfigFile(t) | ||||||
| 	assert.NoError(err) |  | ||||||
| 	defer os.RemoveAll(tmpdir) | 	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) | 	spec, err := compatoci.ParseConfigJSON(bundlePath) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| @@ -477,7 +385,7 @@ func TestCreateContainer(t *testing.T) { | |||||||
| 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | 	spec.Annotations[testSandboxIDAnnotation] = testSandboxID | ||||||
|  |  | ||||||
| 	// rewrite file | 	// rewrite file | ||||||
| 	err = writeOCIConfigFile(spec, ociConfigFile) | 	err = ktu.WriteOCIConfigFile(spec, ociConfigFile) | ||||||
| 	assert.NoError(err) | 	assert.NoError(err) | ||||||
|  |  | ||||||
| 	rootFs := vc.RootFs{Mounted: true} | 	rootFs := vc.RootFs{Mounted: true} | ||||||
|   | |||||||
| @@ -7,20 +7,15 @@ | |||||||
| package katautils | package katautils | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" |  | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" |  | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils" | 	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" | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -28,173 +23,14 @@ const ( | |||||||
| 	testDirMode  = os.FileMode(0750) | 	testDirMode  = os.FileMode(0750) | ||||||
| 	testFileMode = os.FileMode(0640) | 	testFileMode = os.FileMode(0640) | ||||||
|  |  | ||||||
| 	// small docker image used to create root filesystems from |  | ||||||
| 	testDockerImage = "busybox" |  | ||||||
|  |  | ||||||
| 	testSandboxID   = "99999999-9999-9999-99999999999999999" | 	testSandboxID   = "99999999-9999-9999-99999999999999999" | ||||||
| 	testContainerID = "1" | 	testContainerID = "1" | ||||||
| 	testBundle      = "bundle" |  | ||||||
| 	specConfig      = "config.json" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	testDir = "" | 	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 { | func createFile(file, contents string) error { | ||||||
| 	return ioutil.WriteFile(file, []byte(contents), testFileMode) | 	return ioutil.WriteFile(file, []byte(contents), testFileMode) | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user