mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-23 01:04:25 +01:00
This commit will allow for better performance regarding the time spent to retrieve the sandbox ID related to a container ID. The way it works is by relying on a specific mapping between container IDs and sanbox IDs, meaning it allows to retrieve directly the sandbox ID related to a container ID from the CLI. This lowers complexity from O(n²) to O(1), because we don't need to call into ListPod() which was parsing all the pods and all the containers on the system everytime the CLI need to retrieve this mapping. This commit also updates the whole unit tests as a consequence. This is involving most of them since they were all relying on ListPod() before. Fixes #212 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
745 lines
20 KiB
Go
745 lines
20 KiB
Go
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
|
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
func TestExecCLIFunction(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
flagSet := &flag.FlagSet{}
|
|
app := cli.NewApp()
|
|
ctx := cli.NewContext(app, flagSet, nil)
|
|
|
|
fn, ok := startCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
// no container-id in the Metadata
|
|
err := fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
path, err := createTempContainerIDMapping("xyz", "xyz")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
// pass container-id
|
|
flagSet = flag.NewFlagSet("container-id", flag.ContinueOnError)
|
|
flagSet.Parse([]string{"xyz"})
|
|
ctx = cli.NewContext(app, flagSet, nil)
|
|
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.True(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func TestExecuteErrors(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
// missing container id
|
|
err := execute(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
// StatusSandbox error
|
|
flagSet.Parse([]string{testContainerID})
|
|
err = execute(ctx)
|
|
assert.Error(err)
|
|
assert.True(vcmock.IsMockError(err))
|
|
|
|
// Config path missing in annotations
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
}
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, vc.State{}, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
err = execute(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
// Container state undefined
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations = map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
containerState := vc.State{}
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
|
|
}
|
|
|
|
err = execute(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
// Container paused
|
|
containerState = vc.State{
|
|
State: vc.StatePaused,
|
|
}
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
|
|
}
|
|
|
|
err = execute(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
// Container stopped
|
|
containerState = vc.State{
|
|
State: vc.StateStopped,
|
|
}
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
|
|
}
|
|
|
|
err = execute(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func TestExecuteErrorReadingProcessJson(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
// non-existent path
|
|
processPath := filepath.Join(tmpdir, "process.json")
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
flagSet.String("process", processPath, "")
|
|
flagSet.Parse([]string{testContainerID})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
// Note: flags can only be tested with the CLI command function
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func TestExecuteErrorOpeningConsole(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
consoleSock := filepath.Join(tmpdir, "console-sock")
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
flagSet.String("console-socket", consoleSock, "")
|
|
flagSet.Parse([]string{testContainerID})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
// Note: flags can only be tested with the CLI command function
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func testExecParamsSetup(t *testing.T, pidFilePath, consolePath string, detach bool) *flag.FlagSet {
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
|
|
flagSet.String("pid-file", pidFilePath, "")
|
|
flagSet.String("console", consolePath, "")
|
|
flagSet.String("console-socket", "", "")
|
|
flagSet.Bool("detach", detach, "")
|
|
flagSet.String("process-label", "testlabel", "")
|
|
flagSet.Bool("no-subreaper", false, "")
|
|
|
|
return flagSet
|
|
}
|
|
|
|
func TestExecuteWithFlags(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
|
|
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, false)
|
|
flagSet.String("user", "root", "")
|
|
flagSet.String("cwd", "/home/root", "")
|
|
flagSet.String("apparmor", "/tmp/profile", "")
|
|
flagSet.Bool("no-new-privs", false, "")
|
|
|
|
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
// EnterContainer error
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.True(vcmock.IsMockError(err))
|
|
|
|
testingImpl.EnterContainerFunc = func(sandboxID, containerID string, cmd vc.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
|
|
return &vcmock.Sandbox{}, &vcmock.Container{}, &vc.Process{}, nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.EnterContainerFunc = nil
|
|
os.Remove(pidFilePath)
|
|
}()
|
|
|
|
// Process not running error
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
|
|
os.Remove(pidFilePath)
|
|
|
|
// Process ran and exited successfully
|
|
testingImpl.EnterContainerFunc = func(sandboxID, containerID string, cmd vc.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
|
|
// create a fake container process
|
|
workload := []string{"cat", "/dev/null"}
|
|
command := exec.Command(workload[0], workload[1:]...)
|
|
err := command.Start()
|
|
assert.NoError(err, "Unable to start process %v: %s", workload, err)
|
|
|
|
vcProcess := vc.Process{}
|
|
vcProcess.Pid = command.Process.Pid
|
|
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.EnterContainerFunc = nil
|
|
os.Remove(pidFilePath)
|
|
}()
|
|
|
|
// Should get an exit code when run in non-detached mode.
|
|
err = fn(ctx)
|
|
_, ok = err.(*cli.ExitError)
|
|
assert.True(ok, true, "Exit code not received for fake workload process")
|
|
}
|
|
|
|
func TestExecuteWithFlagsDetached(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
detach := true
|
|
|
|
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, detach)
|
|
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
testingImpl.EnterContainerFunc = func(sandboxID, containerID string, cmd vc.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
|
|
// create a fake container process
|
|
workload := []string{"cat", "/dev/null"}
|
|
command := exec.Command(workload[0], workload[1:]...)
|
|
err := command.Start()
|
|
assert.NoError(err, "Unable to start process %v: %s", workload, err)
|
|
|
|
vcProcess := vc.Process{}
|
|
vcProcess.Pid = command.Process.Pid
|
|
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.EnterContainerFunc = nil
|
|
os.Remove(pidFilePath)
|
|
}()
|
|
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
err = fn(ctx)
|
|
assert.NoError(err)
|
|
}
|
|
|
|
func TestExecuteWithInvalidProcessJson(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
detach := false
|
|
|
|
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, detach)
|
|
|
|
processPath := filepath.Join(tmpdir, "process.json")
|
|
flagSet.String("process", processPath, "")
|
|
|
|
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
|
|
assert.NoError(err)
|
|
|
|
// invalidate the JSON
|
|
_, err = f.WriteString("{")
|
|
assert.NoError(err)
|
|
f.Close()
|
|
|
|
defer os.Remove(processPath)
|
|
|
|
flagSet.Parse([]string{testContainerID})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func TestExecuteWithValidProcessJson(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
|
|
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, false)
|
|
|
|
processPath := filepath.Join(tmpdir, "process.json")
|
|
flagSet.String("process", processPath, "")
|
|
|
|
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
processJSON := `{
|
|
"consoleSize": {
|
|
"height": 15,
|
|
"width": 15
|
|
},
|
|
"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": "/"
|
|
}`
|
|
|
|
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
|
|
assert.NoError(err)
|
|
|
|
_, err = f.WriteString(processJSON)
|
|
assert.NoError(err)
|
|
f.Close()
|
|
|
|
defer os.Remove(processPath)
|
|
|
|
workload := []string{"cat", "/dev/null"}
|
|
|
|
testingImpl.EnterContainerFunc = func(sandboxID, containerID string, cmd vc.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
|
|
// create a fake container process
|
|
command := exec.Command(workload[0], workload[1:]...)
|
|
err := command.Start()
|
|
assert.NoError(err, "Unable to start process %v: %s", workload, err)
|
|
|
|
vcProcess := vc.Process{}
|
|
vcProcess.Pid = command.Process.Pid
|
|
|
|
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.EnterContainerFunc = nil
|
|
os.Remove(pidFilePath)
|
|
}()
|
|
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
err = fn(ctx)
|
|
exitErr, ok := err.(*cli.ExitError)
|
|
assert.True(ok, true, "Exit code not received for fake workload process")
|
|
assert.Equal(exitErr.ExitCode(), 0, "Exit code should have been 0 for fake workload %s", workload)
|
|
}
|
|
|
|
func TestExecuteWithInvalidEnvironment(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
processPath := filepath.Join(tmpdir, "process.json")
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
flagSet.String("process", processPath, "")
|
|
flagSet.Parse([]string{testContainerID})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
configPath := testConfigSetup(t)
|
|
configJSON, err := readOCIConfigJSON(configPath)
|
|
assert.NoError(err)
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
|
|
vcAnnotations.ConfigJSONKey: configJSON,
|
|
}
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(path)
|
|
|
|
testingImpl.StatusContainerFunc = func(sandboxID, containerID string) (vc.ContainerStatus, error) {
|
|
return newSingleContainerStatus(testContainerID, state, annotations), nil
|
|
}
|
|
|
|
defer func() {
|
|
testingImpl.StatusContainerFunc = nil
|
|
}()
|
|
|
|
processJSON := `{
|
|
"env": [
|
|
"TERM="
|
|
]
|
|
}`
|
|
|
|
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
|
|
assert.NoError(err)
|
|
|
|
_, err = f.WriteString(processJSON)
|
|
assert.NoError(err)
|
|
f.Close()
|
|
|
|
defer os.Remove(processPath)
|
|
|
|
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
|
|
assert.True(ok)
|
|
|
|
// vcAnnotations.EnvVars error due to incorrect environment
|
|
err = fn(ctx)
|
|
assert.Error(err)
|
|
assert.False(vcmock.IsMockError(err))
|
|
}
|
|
|
|
func TestGenerateExecParams(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
consoleSocket := "/tmp/console-sock"
|
|
processLabel := "testlabel"
|
|
user := "root"
|
|
cwd := "cwd"
|
|
apparmor := "apparmorProf"
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
flagSet.String("pid-file", pidFilePath, "")
|
|
flagSet.String("console", consolePath, "")
|
|
flagSet.String("console-socket", consoleSocket, "")
|
|
flagSet.String("process-label", processLabel, "")
|
|
|
|
flagSet.String("user", user, "")
|
|
flagSet.String("cwd", cwd, "")
|
|
flagSet.String("apparmor", apparmor, "")
|
|
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
process := &oci.CompatOCIProcess{}
|
|
params, err := generateExecParams(ctx, process)
|
|
assert.NoError(err)
|
|
|
|
assert.Equal(params.pidFile, pidFilePath)
|
|
assert.Equal(params.console, consolePath)
|
|
assert.Equal(params.consoleSock, consoleSocket)
|
|
assert.Equal(params.processLabel, processLabel)
|
|
assert.Equal(params.noSubreaper, false)
|
|
assert.Equal(params.detach, false)
|
|
|
|
assert.Equal(params.ociProcess.Terminal, false)
|
|
assert.Equal(params.ociProcess.User.UID, uint32(0))
|
|
assert.Equal(params.ociProcess.User.GID, uint32(0))
|
|
assert.Equal(params.ociProcess.Cwd, cwd)
|
|
assert.Equal(params.ociProcess.ApparmorProfile, apparmor)
|
|
}
|
|
|
|
func TestGenerateExecParamsWithProcessJsonFile(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
pidFilePath := filepath.Join(tmpdir, "pid")
|
|
consolePath := "/dev/ptmx"
|
|
consoleSocket := "/tmp/console-sock"
|
|
detach := true
|
|
processLabel := "testlabel"
|
|
|
|
flagSet := flag.NewFlagSet("", 0)
|
|
flagSet.String("pid-file", pidFilePath, "")
|
|
flagSet.String("console", consolePath, "")
|
|
flagSet.String("console-socket", consoleSocket, "")
|
|
flagSet.Bool("detach", detach, "")
|
|
flagSet.String("process-label", processLabel, "")
|
|
|
|
processPath := filepath.Join(tmpdir, "process.json")
|
|
flagSet.String("process", processPath, "")
|
|
|
|
flagSet.Parse([]string{testContainerID})
|
|
ctx := cli.NewContext(cli.NewApp(), flagSet, nil)
|
|
|
|
processJSON := `{
|
|
"consoleSize": {
|
|
"height": 15,
|
|
"width": 15
|
|
},
|
|
"terminal": true,
|
|
"user": {
|
|
"uid": 0,
|
|
"gid": 0
|
|
},
|
|
"args": [
|
|
"sh"
|
|
],
|
|
"env": [
|
|
"TERM=xterm",
|
|
"foo=bar"
|
|
],
|
|
"cwd": "/"
|
|
}`
|
|
|
|
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
|
|
assert.NoError(err)
|
|
|
|
_, err = f.WriteString(processJSON)
|
|
assert.NoError(err)
|
|
f.Close()
|
|
|
|
defer os.Remove(processPath)
|
|
|
|
process := &oci.CompatOCIProcess{}
|
|
params, err := generateExecParams(ctx, process)
|
|
assert.NoError(err)
|
|
|
|
assert.Equal(params.pidFile, pidFilePath)
|
|
assert.Equal(params.console, consolePath)
|
|
assert.Equal(params.consoleSock, consoleSocket)
|
|
assert.Equal(params.processLabel, processLabel)
|
|
assert.Equal(params.noSubreaper, false)
|
|
assert.Equal(params.detach, detach)
|
|
|
|
assert.Equal(params.ociProcess.Terminal, true)
|
|
assert.Equal(params.ociProcess.ConsoleSize.Height, uint(15))
|
|
assert.Equal(params.ociProcess.ConsoleSize.Width, uint(15))
|
|
assert.Equal(params.ociProcess.User.UID, uint32(0))
|
|
assert.Equal(params.ociProcess.User.GID, uint32(0))
|
|
assert.Equal(params.ociProcess.Cwd, "/")
|
|
assert.Equal(params.ociProcess.Env[0], "TERM=xterm")
|
|
assert.Equal(params.ociProcess.Env[1], "foo=bar")
|
|
}
|