diff --git a/cli/exec.go b/cli/exec.go index 2817ce724..d5be5fba9 100644 --- a/cli/exec.go +++ b/cli/exec.go @@ -210,9 +210,11 @@ func execute(context *cli.Context) error { params.cID = status.ID - // container MUST be running - if status.State.State != vc.StateRunning { - return fmt.Errorf("Container %s is not running", params.cID) + // container MUST be ready or running. + if status.State.State != vc.StateReady && + status.State.State != vc.StateRunning { + return fmt.Errorf("Container %s is not ready or running", + params.cID) } envVars, err := oci.EnvVars(params.ociProcess.Env) diff --git a/cli/exec_test.go b/cli/exec_test.go index 6efbeb546..64ac26ed7 100644 --- a/cli/exec_test.go +++ b/cli/exec_test.go @@ -89,7 +89,7 @@ func TestExecuteErrors(t *testing.T) { assert.Error(err) assert.False(vcmock.IsMockError(err)) - // Container not running + // Container state undefined configPath := testConfigSetup(t) configJSON, err := readOCIConfigJSON(configPath) assert.NoError(err) @@ -99,13 +99,34 @@ func TestExecuteErrors(t *testing.T) { vcAnnotations.ConfigJSONKey: configJSON, } + containerState := vc.State{} testingImpl.ListPodFunc = func() ([]vc.PodStatus, error) { - return newSingleContainerPodStatusList(testPodID, testContainerID, vc.State{}, vc.State{}, annotations), nil + return newSingleContainerPodStatusList(testPodID, testContainerID, vc.State{}, containerState, annotations), nil } - defer func() { - testingImpl.ListPodFunc = nil - }() + err = execute(ctx) + assert.Error(err) + assert.False(vcmock.IsMockError(err)) + + // Container paused + containerState = vc.State{ + State: vc.StatePaused, + } + testingImpl.ListPodFunc = func() ([]vc.PodStatus, error) { + return newSingleContainerPodStatusList(testPodID, testContainerID, vc.State{}, containerState, annotations), nil + } + + err = execute(ctx) + assert.Error(err) + assert.False(vcmock.IsMockError(err)) + + // Container stopped + containerState = vc.State{ + State: vc.StateStopped, + } + testingImpl.ListPodFunc = func() ([]vc.PodStatus, error) { + return newSingleContainerPodStatusList(testPodID, testContainerID, vc.State{}, containerState, annotations), nil + } err = execute(ctx) assert.Error(err) diff --git a/virtcontainers/container.go b/virtcontainers/container.go index fa949fa96..91164c81c 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -627,8 +627,10 @@ func (c *Container) enter(cmd Cmd) (*Process, error) { return nil, err } - if c.state.State != StateRunning { - return nil, fmt.Errorf("Container not running, impossible to enter") + if c.state.State != StateReady && + c.state.State != StateRunning { + return nil, fmt.Errorf("Container not ready or running, " + + "impossible to enter") } process, err := c.pod.agent.exec(c.pod, *c, cmd) diff --git a/virtcontainers/container_test.go b/virtcontainers/container_test.go index 1fac1c207..5950b872e 100644 --- a/virtcontainers/container_test.go +++ b/virtcontainers/container_test.go @@ -336,3 +336,29 @@ func TestContainerRemoveResources(t *testing.T) { err = c.removeResources() assert.Nil(err) } + +func TestContainerEnterErrorsOnContainerStates(t *testing.T) { + assert := assert.New(t) + c := &Container{ + pod: &Pod{ + state: State{ + State: StateRunning, + }, + }, + } + cmd := Cmd{} + + // Container state undefined + _, err := c.enter(cmd) + assert.Error(err) + + // Container paused + c.state.State = StatePaused + _, err = c.enter(cmd) + assert.Error(err) + + // Container stopped + c.state.State = StateStopped + _, err = c.enter(cmd) + assert.Error(err) +}