Merge "Extend container interface with mounts get log opts"

This commit is contained in:
Zuul 2021-02-09 01:11:37 +00:00 committed by Gerrit Code Review
commit 8b19ced1b8
6 changed files with 87 additions and 29 deletions

View File

@ -123,7 +123,7 @@ func (options *BootstrapContainerOptions) GetContainerStatus() (container.Status
var exitCode int
exitCode = state.ExitCode
if exitCode > 0 {
reader, err := options.Container.GetContainerLogs()
reader, err := options.Container.GetContainerLogs(container.GetLogOptions{Stderr: true, Follow: true})
if err != nil {
log.Printf("Error while trying to retrieve the container logs")
return BootNullString, err
@ -197,7 +197,7 @@ func (options *BootstrapContainerOptions) CreateBootstrapContainer() error {
fmt.Sprintf("%s=%s", envBootstrapVolume, containerVolMount),
}
err := options.Container.RunCommand(container.RunCommandOptions{EnvVars: envVars, VolumeMounts: vols})
err := options.Container.RunCommand(container.RunCommandOptions{EnvVars: envVars, Binds: vols})
if err != nil {
return err
}

View File

@ -134,7 +134,7 @@ func (opts BootstrapIsoOptions) CreateBootstrapIso() error {
fmt.Sprintf("NO_PROXY=%s", os.Getenv("NO_PROXY")),
}
err = opts.Builder.RunCommand(container.RunCommandOptions{EnvVars: envVars, VolumeMounts: vols})
err = opts.Builder.RunCommand(container.RunCommandOptions{EnvVars: envVars, Binds: vols})
if err != nil {
return err
}
@ -143,7 +143,7 @@ func (opts BootstrapIsoOptions) CreateBootstrapIso() error {
if log.DebugEnabled() {
var cLogs io.ReadCloser
cLogs, err = opts.Builder.GetContainerLogs()
cLogs, err = opts.Builder.GetContainerLogs(container.GetLogOptions{Stderr: true, Follow: true})
if err != nil {
log.Printf("failed to read container logs %s", err)
} else {

View File

@ -19,6 +19,11 @@ import (
"io"
)
const (
// ContainerDriverDocker indicates that docker driver should be used in container constructor
ContainerDriverDocker = "docker"
)
// Status type provides container status
type Status string
@ -36,7 +41,7 @@ type State struct {
type Container interface {
ImagePull() error
RunCommand(RunCommandOptions) error
GetContainerLogs() (io.ReadCloser, error)
GetContainerLogs(GetLogOptions) (io.ReadCloser, error)
InspectContainer() (State, error)
WaitUntilFinished() error
RmContainer() error
@ -45,13 +50,31 @@ type Container interface {
// RunCommandOptions options for RunCommand
type RunCommandOptions struct {
Privileged bool
Privileged bool
HostNewtork bool
Cmd []string
EnvVars []string
VolumeMounts []string
Cmd []string
EnvVars []string
Binds []string
Input io.Reader
Mounts []Mount
Input io.Reader
}
// Mount describes mount settings
type Mount struct {
ReadOnly bool
Type string
Dst string
Src string
}
// GetLogOptions options for getting logs
// If both Stderr and Stdout are specified the logs will contain both stderr and stdout
type GetLogOptions struct {
Stderr bool
Stdout bool
Follow bool
}
// NewContainer returns instance of Container interface implemented by particular driver
@ -63,7 +86,7 @@ func NewContainer(ctx context.Context, driver string, url string) (Container, er
switch driver {
case "":
return nil, ErrNoContainerDriver{}
case "docker":
case ContainerDriverDocker:
cli, err := NewDockerClient(ctx)
if err != nil {
return nil, err

View File

@ -24,6 +24,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
@ -174,18 +175,36 @@ func (c *DockerContainer) getConfig(opts RunCommandOptions) (container.Config, c
if err != nil {
return container.Config{}, container.HostConfig{}, err
}
mounts := []mount.Mount{}
for _, mnt := range opts.Mounts {
mounts = append(mounts, mount.Mount{
Type: mount.Type(mnt.Type),
Source: mnt.Src,
Target: mnt.Dst,
ReadOnly: mnt.ReadOnly,
})
}
cCfg := container.Config{
Image: c.imageURL,
Cmd: cmd,
AttachStdin: true,
OpenStdin: true,
Env: opts.EnvVars,
Tty: true,
Image: c.imageURL,
Cmd: cmd,
AttachStdin: true,
StdinOnce: true,
OpenStdin: true,
AttachStderr: true,
AttachStdout: true,
Env: opts.EnvVars,
}
hCfg := container.HostConfig{
Binds: opts.VolumeMounts,
Binds: opts.Binds,
Mounts: mounts,
Privileged: opts.Privileged,
}
if opts.HostNewtork {
hCfg.NetworkMode = "host"
}
return cCfg, hCfg, nil
}
@ -268,6 +287,8 @@ func (c *DockerContainer) RunCommand(opts RunCommandOptions) (err error) {
if attachErr != nil {
return attachErr
}
defer conn.Close()
if _, err = io.Copy(conn.Conn, opts.Input); err != nil {
return err
}
@ -282,8 +303,12 @@ func (c *DockerContainer) RunCommand(opts RunCommandOptions) (err error) {
}
// GetContainerLogs returns logs from the container as io.ReadCloser
func (c *DockerContainer) GetContainerLogs() (io.ReadCloser, error) {
return c.dockerClient.ContainerLogs(c.ctx, c.id, types.ContainerLogsOptions{ShowStdout: true, Follow: true})
func (c *DockerContainer) GetContainerLogs(opts GetLogOptions) (io.ReadCloser, error) {
return c.dockerClient.ContainerLogs(c.ctx, c.id, types.ContainerLogsOptions{
ShowStderr: opts.Stderr,
Follow: opts.Follow,
ShowStdout: opts.Stdout,
})
}
// RmContainer kills and removes a container from the docker host.

View File

@ -286,6 +286,7 @@ func TestRunCommand(t *testing.T) {
cmd []string
containerInput io.Reader
volumeMounts []string
mounts []Mount
debug bool
mockDockerClient mockDockerClient
expectedRunErr error
@ -329,7 +330,15 @@ func TestRunCommand(t *testing.T) {
return conn, nil
},
},
expectedRunErr: nil,
expectedRunErr: nil,
mounts: []Mount{
{
ReadOnly: true,
Type: "bind",
Dst: "/dev/vda0",
Src: "/dev/vd3",
},
},
expectedWaitErr: nil,
assertF: func(t *testing.T) {},
},
@ -422,9 +431,10 @@ func TestRunCommand(t *testing.T) {
for _, tt := range tests {
cnt := getDockerContainerMock(tt.mockDockerClient)
actualErr := cnt.RunCommand(RunCommandOptions{
Input: tt.containerInput,
Cmd: tt.cmd,
VolumeMounts: tt.volumeMounts,
Input: tt.containerInput,
Cmd: tt.cmd,
Binds: tt.volumeMounts,
Mounts: tt.mounts,
})
assert.Equal(t, tt.expectedRunErr, actualErr)
actualErr = cnt.WaitUntilFinished()
@ -468,12 +478,12 @@ func TestRunCommandOutput(t *testing.T) {
for _, tt := range tests {
cnt := getDockerContainerMock(tt.mockDockerClient)
actualErr := cnt.RunCommand(RunCommandOptions{
Input: tt.containerInput,
Cmd: tt.cmd,
VolumeMounts: tt.volumeMounts,
Input: tt.containerInput,
Cmd: tt.cmd,
Binds: tt.volumeMounts,
})
assert.Equal(t, tt.expectedErr, actualErr)
actualRes, actualErr := cnt.GetContainerLogs()
actualRes, actualErr := cnt.GetContainerLogs(GetLogOptions{Stdout: true, Follow: true})
require.NoError(t, actualErr)
var actualResBytes []byte

View File

@ -42,7 +42,7 @@ func (mc *MockContainer) RunCommand(container.RunCommandOptions) error {
}
// GetContainerLogs Container interface implementation for unit test purposes
func (mc *MockContainer) GetContainerLogs() (io.ReadCloser, error) {
func (mc *MockContainer) GetContainerLogs(container.GetLogOptions) (io.ReadCloser, error) {
return mc.MockGetContainerLogs()
}