Skip to content

Commit

Permalink
Add networking (#10)
Browse files Browse the repository at this point in the history
* add networking to containers to support non-legacy link networking

* gofmt
  • Loading branch information
jakesylvestre authored Mar 14, 2021
1 parent cf6f8e2 commit 71a4012
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 29 deletions.
27 changes: 17 additions & 10 deletions container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ type TestClient struct {
Client
}

func (c TestClient) CreateTestContainer() (id string, err error) {
func (c TestClient) CreateTestContainer(network string) (id string, err error) {
created, err := c.CreateContainer(&container.Config{
Image: "docker.io/library/alpine",
Tty: false,
}, nil, nil, nil, "")
}, &container.HostConfig{
NetworkMode: container.NetworkMode(network),
}, nil, nil, "")

if err != nil {
return id, err
Expand All @@ -33,22 +35,27 @@ func (c TestClient) CreateTestContainer() (id string, err error) {
}

func TestContainerLifecycle(t *testing.T) {
output := gofakeit.Word()
client := TestClient{NewDockerClient()}
defer func() {
Nil(t, client.TeardownSession())
}()
id, err := client.CreateTestContainer()
// we run this twice to ensure teardown occured correctly
containerNetworkName := gofakeit.Word()
containerOutput := gofakeit.Word()

networkID, err := client.CreateNetwork(containerNetworkName)
Nil(t, err)

id, err := client.CreateTestContainer(networkID)
Nil(t, err)

res, err := client.Exec(id, []string{"echo", output})
res, err := client.Exec(id, []string{"echo", containerOutput})
Nil(t, err)

if res.ExitCode != 0 && res.StdErr != "" && res.StdOut != output {
t.Errorf("expeceted output to equal %s", "hi")
if res.ExitCode != 0 && res.StdErr != "" && res.StdOut != containerOutput {
t.Errorf("expeceted containerOutput to equal %s", "hi")
}

// TODO verify
_, err = client.ContainerStatus(id)
Nil(t, err)

Nil(t, client.TeardownSession())
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/google/go-cmp v0.5.4 // indirect
github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0 // indirect
github.com/hashicorp/go-multierror v1.1.1
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand Down
24 changes: 24 additions & 0 deletions network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package docker

import "github.com/docker/docker/api/types"

// CreateNetwork creates a docker network that can
// be used for communication in between containers
// see: https://docs.docker.com/network/ for details
func (c Client) CreateNetwork(name string) (networkID string, err error) {
networkResponse, err := c.NetworkCreate(c.Ctx, name,
types.NetworkCreate{
CheckDuplicate: true,
Attachable: true,
Labels: c.getSessionLabels(),
})
if err != nil {
return "", err
}
return networkResponse.ID, err
}

// RemoveNetwork removes a network by id
func (c Client) RemoveNetwork(networkID string) error {
return c.NetworkRemove(c.Ctx, networkID)
}
50 changes: 34 additions & 16 deletions teardown.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
package docker

import (
"fmt"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/hashicorp/go-multierror"
)

// TeardownSession removes all resources created during the session
func (c *Client) TeardownSession() (err error) {
err = c.TeardownSessionContainers()
if err != nil {
return err
err = multierror.Append(err)
}
err = c.TeardownSessionVolumes()
if err != nil {
err = multierror.Append(err)
}
err = c.TeardownSessionNetworks()
if err != nil {
err = multierror.Append(err)
}
return c.TeardownSessionVolumes()
return err
}

// TeardownSessionVolumes removes containers created in the current session using RemoveVolume
// the current session is determined based on the Client so this method should be called
// once per Client
func (c *Client) TeardownSessionVolumes() error {
volumes, err := c.VolumeList(c.Ctx, filters.NewArgs(filters.KeyValuePair{
Key: "label",
Value: fmt.Sprintf("sessionId=%s", c.SessionID),
}))
func (c *Client) TeardownSessionVolumes() (err error) {
volumes, err := c.VolumeList(c.Ctx, filterByLabels(c.getSessionLabels()))

if err != nil {
return err
Expand All @@ -39,16 +42,31 @@ func (c *Client) TeardownSessionVolumes() error {
return err
}

// TeardownSessionNetworks removes containers created in the current session using StopContainer
// and RemoveContainer the current session is determined based on the Client
// so this method should be called once per Client
func (c *Client) TeardownSessionNetworks() (err error) {
networks, err := c.NetworkList(c.Ctx, types.NetworkListOptions{Filters: filterByLabels(c.getSessionLabels())})
if err != nil {
return err
}

for _, network := range networks {
err = c.RemoveNetwork(network.ID)
if err != nil {
return err
}
}
return err
}

// TeardownSessionContainers removes containers created in the current session using StopContainer
// and RemoveContainer the current session is determined based on the Client
// so this method should be called once per Client
func (c *Client) TeardownSessionContainers() error {
func (c *Client) TeardownSessionContainers() (err error) {
filter := types.ContainerListOptions{
All: true,
Filters: filters.NewArgs(filters.KeyValuePair{
Key: "label",
Value: fmt.Sprintf("sessionId=%s", c.SessionID),
}),
All: true,
Filters: filterByLabels(c.getSessionLabels()),
}

containers, err := c.ContainerList(c.Ctx, filter)
Expand Down
27 changes: 27 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package docker

import (
"fmt"

"github.com/docker/docker/api/types/filters"
)

// getSessionLabels gets labels set for all resources created in this session
func (c Client) getSessionLabels() map[string]string {
return map[string]string{
"sessionId": c.SessionID,
"created-by": "docker-utils",
}
}

// filterByLabels creates filters.Args based on a set of labels
func filterByLabels(labels map[string]string) (args filters.Args) {
var kvps []filters.KeyValuePair
for key, value := range labels {
kvps = append(kvps, filters.KeyValuePair{
Key: "label",
Value: fmt.Sprintf("%s=%s", key, value),
})
}
return filters.NewArgs(kvps...)
}
4 changes: 1 addition & 3 deletions volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ func (c *Client) CreateVolume(name string) (err error) {
vol, err := c.VolumeCreate(c.Ctx, volume.VolumeCreateBody{
Driver: Driver,
Name: name,
Labels: map[string]string{
"sessionId": c.SessionID,
},
Labels: c.getSessionLabels(),
})
if err != nil {
return err
Expand Down

0 comments on commit 71a4012

Please sign in to comment.