Extending Container interface and package
Adding the following method to the interface and implementation for docker container: - InspectContainer() - used to determine container status Change-Id: I4a8096f4f5addad31daa5038a30b1ffcf1d424e9
This commit is contained in:
parent
a360ebf9da
commit
f4e532e91a
@ -27,6 +27,7 @@ import (
|
|||||||
|
|
||||||
api "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
|
api "opendev.org/airship/airshipctl/pkg/api/v1alpha1"
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/container"
|
||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
"opendev.org/airship/airshipctl/pkg/log"
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
"opendev.org/airship/airshipctl/testutil"
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
@ -39,6 +40,7 @@ type mockContainer struct {
|
|||||||
rmContainer func() error
|
rmContainer func() error
|
||||||
getID func() string
|
getID func() string
|
||||||
waitUntilFinished func() error
|
waitUntilFinished func() error
|
||||||
|
inspectContainer func() (container.State, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *mockContainer) ImagePull() error {
|
func (mc *mockContainer) ImagePull() error {
|
||||||
@ -65,6 +67,10 @@ func (mc *mockContainer) WaitUntilFinished() error {
|
|||||||
return mc.waitUntilFinished()
|
return mc.waitUntilFinished()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *mockContainer) InspectContainer() (container.State, error) {
|
||||||
|
return mc.inspectContainer()
|
||||||
|
}
|
||||||
|
|
||||||
const testID = "TESTID"
|
const testID = "TESTID"
|
||||||
|
|
||||||
func TestBootstrapIso(t *testing.T) {
|
func TestBootstrapIso(t *testing.T) {
|
||||||
|
32
pkg/container/constants.go
Normal file
32
pkg/container/constants.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package container
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CreatedContainerStatus indicates container has been created
|
||||||
|
CreatedContainerStatus = "created"
|
||||||
|
// RunningContainerStatus indicates container is in running state
|
||||||
|
RunningContainerStatus = "running"
|
||||||
|
// PausedContainerStatus indicates container is in paused state
|
||||||
|
PausedContainerStatus = "paused"
|
||||||
|
// RestartedContainerStatus indicates container has re-started
|
||||||
|
RestartedContainerStatus = "restarted"
|
||||||
|
// RemovingContainerStatus indicates container is being removed
|
||||||
|
RemovingContainerStatus = "removing"
|
||||||
|
// ExitedContainerStatus indicates container has exited
|
||||||
|
ExitedContainerStatus = "exited"
|
||||||
|
// DeadContainerStatus indicates container is dead
|
||||||
|
DeadContainerStatus = "dead"
|
||||||
|
)
|
@ -19,6 +19,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Status type provides container status
|
||||||
|
type Status string
|
||||||
|
|
||||||
|
// State provides information about the Container
|
||||||
|
type State struct {
|
||||||
|
// ExitCode: returns the container's exit code. Zero means exited normally, otherwise errored
|
||||||
|
ExitCode int
|
||||||
|
// Status: String representation of the container state.
|
||||||
|
Status Status
|
||||||
|
}
|
||||||
|
|
||||||
// Container interface abstraction for container.
|
// Container interface abstraction for container.
|
||||||
// Particular implementation depends on container runtime environment (CRE). Interface
|
// Particular implementation depends on container runtime environment (CRE). Interface
|
||||||
// defines methods that must be implemented for CRE (e.g. docker, containerd or CRI-O)
|
// defines methods that must be implemented for CRE (e.g. docker, containerd or CRI-O)
|
||||||
@ -26,9 +37,10 @@ type Container interface {
|
|||||||
ImagePull() error
|
ImagePull() error
|
||||||
RunCommand([]string, io.Reader, []string, []string) error
|
RunCommand([]string, io.Reader, []string, []string) error
|
||||||
GetContainerLogs() (io.ReadCloser, error)
|
GetContainerLogs() (io.ReadCloser, error)
|
||||||
|
InspectContainer() (State, error)
|
||||||
|
WaitUntilFinished() error
|
||||||
RmContainer() error
|
RmContainer() error
|
||||||
GetID() string
|
GetID() string
|
||||||
WaitUntilFinished() error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContainer returns instance of Container interface implemented by particular driver
|
// NewContainer returns instance of Container interface implemented by particular driver
|
||||||
|
@ -87,6 +87,11 @@ type DockerClient interface {
|
|||||||
string,
|
string,
|
||||||
types.ContainerRemoveOptions,
|
types.ContainerRemoveOptions,
|
||||||
) error
|
) error
|
||||||
|
// ContainerInspect returns the container state
|
||||||
|
ContainerInspect(
|
||||||
|
ctx context.Context,
|
||||||
|
containerID string,
|
||||||
|
) (types.ContainerJSON, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerContainer docker container object wrapper
|
// DockerContainer docker container object wrapper
|
||||||
@ -298,6 +303,21 @@ func (c *DockerContainer) RmContainer() error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InspectContainer inspect the running container
|
||||||
|
func (c *DockerContainer) InspectContainer() (State, error) {
|
||||||
|
json, err := c.dockerClient.ContainerInspect(context.Background(), c.id)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to inspect container status")
|
||||||
|
return State{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
state := State{
|
||||||
|
ExitCode: json.ContainerJSONBase.State.ExitCode,
|
||||||
|
Status: Status(json.ContainerJSONBase.State.Status),
|
||||||
|
}
|
||||||
|
return state, err
|
||||||
|
}
|
||||||
|
|
||||||
// WaitUntilFinished waits unit container command is finished, return an error if failed
|
// WaitUntilFinished waits unit container command is finished, return an error if failed
|
||||||
func (c *DockerContainer) WaitUntilFinished() error {
|
func (c *DockerContainer) WaitUntilFinished() error {
|
||||||
statusCh, errCh := c.dockerClient.ContainerWait(c.ctx, c.id, container.WaitConditionNotRunning)
|
statusCh, errCh := c.dockerClient.ContainerWait(c.ctx, c.id, container.WaitConditionNotRunning)
|
||||||
|
@ -56,6 +56,7 @@ type mockDockerClient struct {
|
|||||||
containerStart func() error
|
containerStart func() error
|
||||||
containerWait func() (<-chan container.ContainerWaitOKBody, <-chan error)
|
containerWait func() (<-chan container.ContainerWaitOKBody, <-chan error)
|
||||||
containerLogs func() (io.ReadCloser, error)
|
containerLogs func() (io.ReadCloser, error)
|
||||||
|
containerInspect func() (types.ContainerJSON, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mdc *mockDockerClient) ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error) {
|
func (mdc *mockDockerClient) ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error) {
|
||||||
@ -119,6 +120,13 @@ func (mdc *mockDockerClient) ContainerRemove(context.Context, string, types.Cont
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mdc *mockDockerClient) ContainerInspect(context.Context, string) (types.ContainerJSON, error) {
|
||||||
|
if mdc.containerInspect != nil {
|
||||||
|
return mdc.containerInspect()
|
||||||
|
}
|
||||||
|
return types.ContainerJSON{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDockerContainerMock(mdc mockDockerClient) *DockerContainer {
|
func getDockerContainerMock(mdc mockDockerClient) *DockerContainer {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cnt := &DockerContainer{
|
cnt := &DockerContainer{
|
||||||
@ -555,3 +563,95 @@ func TestRmContainer(t *testing.T) {
|
|||||||
assert.Equal(t, tt.expectedErr, actualErr)
|
assert.Equal(t, tt.expectedErr, actualErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInspectContainer(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
cli mockDockerClient
|
||||||
|
expectedState State
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// Status: String representation of the container state.
|
||||||
|
// Testing Status == CreatedContainerStatus and ExitCode == 0
|
||||||
|
cli: mockDockerClient{
|
||||||
|
containerInspect: func() (types.ContainerJSON, error) {
|
||||||
|
json := types.ContainerJSON{}
|
||||||
|
json.ContainerJSONBase = &types.ContainerJSONBase{}
|
||||||
|
json.ContainerJSONBase.State = &types.ContainerState{}
|
||||||
|
json.ContainerJSONBase.State.ExitCode = 0
|
||||||
|
json.ContainerJSONBase.State.Status = CreatedContainerStatus
|
||||||
|
return json, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedState: State{
|
||||||
|
ExitCode: 0,
|
||||||
|
Status: CreatedContainerStatus,
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Status: String representation of the container state.
|
||||||
|
// Testing Status == RunningContainerStatus and ExitCode == 0
|
||||||
|
cli: mockDockerClient{
|
||||||
|
containerInspect: func() (types.ContainerJSON, error) {
|
||||||
|
json := types.ContainerJSON{}
|
||||||
|
json.ContainerJSONBase = &types.ContainerJSONBase{}
|
||||||
|
json.ContainerJSONBase.State = &types.ContainerState{}
|
||||||
|
json.ContainerJSONBase.State.ExitCode = 0
|
||||||
|
json.ContainerJSONBase.State.Status = RunningContainerStatus
|
||||||
|
return json, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedState: State{
|
||||||
|
ExitCode: 0,
|
||||||
|
Status: RunningContainerStatus,
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Status: String representation of the container state.
|
||||||
|
// Testing Status == ExitedContainerStatus and ExitCode == 0
|
||||||
|
cli: mockDockerClient{
|
||||||
|
containerInspect: func() (types.ContainerJSON, error) {
|
||||||
|
json := types.ContainerJSON{}
|
||||||
|
json.ContainerJSONBase = &types.ContainerJSONBase{}
|
||||||
|
json.ContainerJSONBase.State = &types.ContainerState{}
|
||||||
|
json.ContainerJSONBase.State.ExitCode = 0
|
||||||
|
json.ContainerJSONBase.State.Status = ExitedContainerStatus
|
||||||
|
return json, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedState: State{
|
||||||
|
ExitCode: 0,
|
||||||
|
Status: ExitedContainerStatus,
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Status: String representation of the container state.
|
||||||
|
// Testing Status == ExitedContainerStatus and ExitCode == 1
|
||||||
|
cli: mockDockerClient{
|
||||||
|
containerInspect: func() (types.ContainerJSON, error) {
|
||||||
|
json := types.ContainerJSON{}
|
||||||
|
json.ContainerJSONBase = &types.ContainerJSONBase{}
|
||||||
|
json.ContainerJSONBase.State = &types.ContainerState{}
|
||||||
|
json.ContainerJSONBase.State.ExitCode = 1
|
||||||
|
json.ContainerJSONBase.State.Status = ExitedContainerStatus
|
||||||
|
return json, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedState: State{
|
||||||
|
ExitCode: 1,
|
||||||
|
Status: ExitedContainerStatus,
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
cnt := getDockerContainerMock(tt.cli)
|
||||||
|
actualState, actualErr := cnt.InspectContainer()
|
||||||
|
assert.Equal(t, tt.expectedState, actualState)
|
||||||
|
assert.Equal(t, tt.expectedErr, actualErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user