Skip to content

Commit

Permalink
Merge pull request #203 from vdice/feat/access-docker-config-options
Browse files Browse the repository at this point in the history
feat(docker.go): access Docker configuration options
  • Loading branch information
silvin-lubecki authored Apr 22, 2020
2 parents 910b5fd + 38767e7 commit bc0cd79
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 8 deletions.
59 changes: 51 additions & 8 deletions driver/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package docker
import (
"archive/tar"
"context"
"errors"
"fmt"
"io"
"io/ioutil"
Expand All @@ -20,6 +21,7 @@ import (
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/stdcopy"
"github.com/docker/docker/registry"
copystructure "github.com/mitchellh/copystructure"
)

// Driver is capable of running Docker invocation images using Docker itself.
Expand All @@ -31,6 +33,8 @@ type Driver struct {
dockerConfigurationOptions []ConfigurationOption
containerOut io.Writer
containerErr io.Writer
containerHostCfg *container.HostConfig
containerCfg *container.Config
}

// Run executes the Docker driver
Expand All @@ -48,6 +52,38 @@ func (d *Driver) AddConfigurationOptions(opts ...ConfigurationOption) {
d.dockerConfigurationOptions = append(d.dockerConfigurationOptions, opts...)
}

// GetContainerConfig returns a copy of the container configuration
// used by the driver during container exec
func (d *Driver) GetContainerConfig() (container.Config, error) {
cpy, err := copystructure.Copy(*d.containerCfg)
if err != nil {
return container.Config{}, err
}

containerCfg, ok := cpy.(container.Config)
if !ok {
return container.Config{}, errors.New("unable to process container config")
}

return containerCfg, nil
}

// GetContainerHostConfig returns a copy of the container host configuration
// used by the driver during container exec
func (d *Driver) GetContainerHostConfig() (container.HostConfig, error) {
cpy, err := copystructure.Copy(*d.containerHostCfg)
if err != nil {
return container.HostConfig{}, err
}

hostCfg, ok := cpy.(container.HostConfig)
if !ok {
return container.HostConfig{}, errors.New("unable to process container host config")
}

return hostCfg, nil
}

// Config returns the Docker driver configuration options
func (d *Driver) Config() map[string]string {
return map[string]string{
Expand Down Expand Up @@ -155,29 +191,27 @@ func (d *Driver) exec(op *driver.Operation) (driver.OperationResult, error) {
env = append(env, fmt.Sprintf("%s=%v", k, v))
}

cfg := &container.Config{
d.containerCfg = &container.Config{
Image: op.Image.Image,
Env: env,
Entrypoint: strslice.StrSlice{"/cnab/app/run"},
AttachStderr: true,
AttachStdout: true,
}

hostCfg := &container.HostConfig{}
for _, opt := range d.dockerConfigurationOptions {
if err := opt(cfg, hostCfg); err != nil {
return driver.OperationResult{}, err
}
d.containerHostCfg = &container.HostConfig{}
if err := d.applyConfigurationOptions(); err != nil {
return driver.OperationResult{}, err
}

resp, err := cli.Client().ContainerCreate(ctx, cfg, hostCfg, nil, "")
resp, err := cli.Client().ContainerCreate(ctx, d.containerCfg, d.containerHostCfg, nil, "")
switch {
case client.IsErrNotFound(err):
fmt.Fprintf(cli.Err(), "Unable to find image '%s' locally\n", op.Image.Image)
if err := pullImage(ctx, cli, op.Image.Image); err != nil {
return driver.OperationResult{}, err
}
if resp, err = cli.Client().ContainerCreate(ctx, cfg, hostCfg, nil, ""); err != nil {
if resp, err = cli.Client().ContainerCreate(ctx, d.containerCfg, d.containerHostCfg, nil, ""); err != nil {
return driver.OperationResult{}, fmt.Errorf("cannot create container: %v", err)
}
case err != nil:
Expand Down Expand Up @@ -259,6 +293,15 @@ func (d *Driver) exec(op *driver.Operation) (driver.OperationResult, error) {
return opResult, err
}

func (d *Driver) applyConfigurationOptions() error {
for _, opt := range d.dockerConfigurationOptions {
if err := opt(d.containerCfg, d.containerHostCfg); err != nil {
return err
}
}
return nil
}

func containerError(containerMessage string, containerErr, fetchErr error) error {
if fetchErr != nil {
return fmt.Errorf("%s: %v. fetching outputs failed: %s", containerMessage, containerErr, fetchErr)
Expand Down
60 changes: 60 additions & 0 deletions driver/docker/docker_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package docker

import (
"testing"

"github.com/cnabio/cnab-go/driver"
"github.com/docker/docker/api/types/container"
"github.com/stretchr/testify/assert"
)

func TestDriver_GetConfigurationOptions(t *testing.T) {
d := &Driver{}
is := assert.New(t)
is.NotNil(d)
is.True(d.Handles(driver.ImageTypeDocker))

t.Run("no configuration options", func(t *testing.T) {
d.containerCfg = &container.Config{}
d.containerHostCfg = &container.HostConfig{}

err := d.applyConfigurationOptions()
is.NoError(err)

cfg, err := d.GetContainerConfig()
is.NoError(err)
is.Equal(container.Config{}, cfg)

hostCfg, err := d.GetContainerHostConfig()
is.NoError(err)
is.Equal(container.HostConfig{}, hostCfg)
})

t.Run("configuration options", func(t *testing.T) {
d.containerCfg = &container.Config{}
d.containerHostCfg = &container.HostConfig{}
d.AddConfigurationOptions(func(cfg *container.Config, hostCfg *container.HostConfig) error {
cfg.User = "cnabby"
hostCfg.Privileged = true
return nil
})

err := d.applyConfigurationOptions()
is.NoError(err)

expectedContainerCfg := container.Config{
User: "cnabby",
}
expectedHostCfg := container.HostConfig{
Privileged: true,
}

cfg, err := d.GetContainerConfig()
is.NoError(err)
is.Equal(expectedContainerCfg, cfg)

hostCfg, err := d.GetContainerHostConfig()
is.NoError(err)
is.Equal(expectedHostCfg, hostCfg)
})
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ require (
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 // indirect
github.com/lib/pq v1.2.0 // indirect
github.com/miekg/pkcs11 v1.0.3 // indirect
github.com/mitchellh/copystructure v1.0.0
github.com/morikuni/aec v1.0.0 // indirect
github.com/oklog/ulid v1.3.1
github.com/opencontainers/runc v0.1.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,13 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/pkcs11 v1.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 h1:cvy4lBOYN3gKfKj8Lzz5Q9TfviP+L7koMHY7SvkyTKs=
github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down

0 comments on commit bc0cd79

Please sign in to comment.