exec: Allow to exec a process on a ready container

If a container is not running, but created/ready instead, this means
a container process exists and that we can actually exec another
process inside this container. The container does not have to be
in running state.

Fixes #120

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2018-03-27 15:08:48 -07:00
parent 9a7813e9ea
commit aa469f4573
4 changed files with 61 additions and 10 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)
}