Skip to content

Commit

Permalink
oci: Restore StatusToOCIState / StateToOCIState
Browse files Browse the repository at this point in the history
These were removed in cleanup commit f607641
They are required for the `delete` command.

Fixes: kata-containers#722

Signed-off-by: Christophe de Dinechin <dinechin@redhat.com>
  • Loading branch information
c3d committed Nov 16, 2021
1 parent 8e37c80 commit dd03c43
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/runtime/cmd/kata-runtime/list.go
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
oci "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/oci"
specs "github.com/opencontainers/runtime-spec/specs-go"
)

const formatOptions = `table or json`
Expand All @@ -36,7 +37,7 @@ type containerState struct {
// InitProcessPid is the init process id in the parent namespace
InitProcessPid int `json:"pid"`
// Status is the current status of the container, running, paused, ...
Status string `json:"status"`
Status specs.ContainerState `json:"status"`
// Bundle is the path on the filesystem to the bundle
Bundle string `json:"bundle"`
// Rootfs is a path to a directory containing the container's root filesystem.
Expand Down
71 changes: 71 additions & 0 deletions src/runtime/virtcontainers/pkg/oci/utils.go
Expand Up @@ -1020,6 +1020,77 @@ func getShmSize(c vc.ContainerConfig) (uint64, error) {
return shmSize, nil
}

// StatusToOCIState translates a virtcontainers container status into an OCI state.
func StatusToOCIState(status vc.ContainerStatus) specs.State {
return specs.State{
Version: specs.Version,
ID: status.ID,
Status: StateToOCIState(status.State.State),
Pid: status.PID,
Bundle: status.Annotations[vcAnnotations.BundlePathKey],
Annotations: status.Annotations,
}
}

// StateToOCIState translates a virtcontainers container state into an OCI one.
func StateToOCIState(state types.StateString) specs.ContainerState {
switch state {
case types.StateReady:
return StateCreated
case types.StateRunning:
return StateRunning
case types.StateStopped:
return StateStopped
case types.StatePaused:
return StatePaused
default:
return ""
}
}

// EnvVars converts an OCI process environment variables slice
// into a virtcontainers EnvVar slice.
func EnvVars(envs []string) ([]types.EnvVar, error) {
var envVars []types.EnvVar

envDelimiter := "="
expectedEnvLen := 2

for _, env := range envs {
envSlice := strings.SplitN(env, envDelimiter, expectedEnvLen)

if len(envSlice) < expectedEnvLen {
return []types.EnvVar{}, fmt.Errorf("Wrong string format: %s, expecting only %v parameters separated with %q",
env, expectedEnvLen, envDelimiter)
}

if envSlice[0] == "" {
return []types.EnvVar{}, fmt.Errorf("Environment variable cannot be empty")
}

envSlice[1] = strings.Trim(envSlice[1], "' ")

envVar := types.EnvVar{
Var: envSlice[0],
Value: envSlice[1],
}

envVars = append(envVars, envVar)
}

return envVars, nil
}

// GetOCIConfig returns an OCI spec configuration from the annotation
// stored into the container status.
func GetOCIConfig(status vc.ContainerStatus) (specs.Spec, error) {
if status.Spec == nil {
return specs.Spec{}, fmt.Errorf("missing OCI spec for container")
}

return *status.Spec, nil
}

// IsCRIOContainerManager check if a Pod is created from CRI-O
func IsCRIOContainerManager(spec *specs.Spec) bool {
if val, ok := spec.Annotations[crioAnnotations.ContainerType]; ok {
Expand Down
203 changes: 203 additions & 0 deletions src/runtime/virtcontainers/pkg/oci/utils_test.go
Expand Up @@ -188,6 +188,209 @@ func TestMinimalSandboxConfig(t *testing.T) {
assert.NoError(os.Remove(configPath))
}

func testStatusToOCIStateSuccessful(t *testing.T, cStatus vc.ContainerStatus, expected specs.State) {
ociState := StatusToOCIState(cStatus)
assert.Exactly(t, ociState, expected)
}

func TestStatusToOCIStateSuccessfulWithReadyState(t *testing.T) {

testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"

state := types.ContainerState{
State: types.StateReady,
}

containerAnnotations := map[string]string{
vcAnnotations.BundlePathKey: tempBundlePath,
}

cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}

expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "created",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}

testStatusToOCIStateSuccessful(t, cStatus, expected)

}

func TestStatusToOCIStateSuccessfulWithRunningState(t *testing.T) {

testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"

state := types.ContainerState{
State: types.StateRunning,
}

containerAnnotations := map[string]string{
vcAnnotations.BundlePathKey: tempBundlePath,
}

cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}

expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "running",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}

testStatusToOCIStateSuccessful(t, cStatus, expected)

}

func TestStatusToOCIStateSuccessfulWithStoppedState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"

state := types.ContainerState{
State: types.StateStopped,
}

containerAnnotations := map[string]string{
vcAnnotations.BundlePathKey: tempBundlePath,
}

cStatus := vc.ContainerStatus{
ID: testContID,
State: state,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}

expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "stopped",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}

testStatusToOCIStateSuccessful(t, cStatus, expected)

}

func TestStatusToOCIStateSuccessfulWithNoState(t *testing.T) {
testContID := "testContID"
testPID := 12345
testRootFs := "testRootFs"

containerAnnotations := map[string]string{
vcAnnotations.BundlePathKey: tempBundlePath,
}

cStatus := vc.ContainerStatus{
ID: testContID,
PID: testPID,
RootFs: testRootFs,
Annotations: containerAnnotations,
}

expected := specs.State{
Version: specs.Version,
ID: testContID,
Status: "",
Pid: testPID,
Bundle: tempBundlePath,
Annotations: containerAnnotations,
}

testStatusToOCIStateSuccessful(t, cStatus, expected)

}

func TestStateToOCIState(t *testing.T) {
var state types.StateString
assert := assert.New(t)

assert.Empty(StateToOCIState(state))

state = types.StateReady
assert.Equal(StateToOCIState(state), "created")

state = types.StateRunning
assert.Equal(StateToOCIState(state), "running")

state = types.StateStopped
assert.Equal(StateToOCIState(state), "stopped")

state = types.StatePaused
assert.Equal(StateToOCIState(state), "paused")
}

func TestEnvVars(t *testing.T) {
assert := assert.New(t)
envVars := []string{"foo=bar", "TERM=xterm", "HOME=/home/foo", "TERM=\"bar\"", "foo=\"\""}
expectecVcEnvVars := []types.EnvVar{
{
Var: "foo",
Value: "bar",
},
{
Var: "TERM",
Value: "xterm",
},
{
Var: "HOME",
Value: "/home/foo",
},
{
Var: "TERM",
Value: "\"bar\"",
},
{
Var: "foo",
Value: "\"\"",
},
}

vcEnvVars, err := EnvVars(envVars)
assert.NoError(err)
assert.Exactly(vcEnvVars, expectecVcEnvVars)
}

func TestMalformedEnvVars(t *testing.T) {
assert := assert.New(t)
envVars := []string{"foo"}
_, err := EnvVars(envVars)
assert.Error(err)

envVars = []string{"=foo"}
_, err = EnvVars(envVars)
assert.Error(err)

envVars = []string{"=foo="}
_, err = EnvVars(envVars)
assert.Error(err)
}

func testGetContainerTypeSuccessful(t *testing.T, annotations map[string]string, expected vc.ContainerType) {
assert := assert.New(t)
containerType, err := GetContainerType(annotations)
Expand Down

0 comments on commit dd03c43

Please sign in to comment.