Browse code

Add an integration/internal/container helper package

To help creating/running/… containers using the client for test integration.
This should make test more readable and reduce duplication a bit.

Usage example

```
// Create a default container named foo
id1 := container.Create(t, ctx, client, container.WithName("foo"))
// Run a default container with a custom command
id2 := container.Run(t, ctx, client, container.WithCmd("echo", "hello world"))
```

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2018/02/10 03:37:55
Showing 7 changed files
... ...
@@ -6,9 +6,8 @@ import (
6 6
 	"testing"
7 7
 	"time"
8 8
 
9
-	"github.com/docker/docker/api/types/container"
10
-	"github.com/docker/docker/api/types/network"
11 9
 	"github.com/docker/docker/client"
10
+	"github.com/docker/docker/integration/internal/container"
12 11
 	"github.com/docker/docker/integration/internal/request"
13 12
 	"github.com/gotestyourself/gotestyourself/poll"
14 13
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -25,10 +24,12 @@ func TestInspectCpusetInConfigPre120(t *testing.T) {
25 25
 
26 26
 	name := "cpusetinconfig-pre120"
27 27
 	// Create container with up to-date-API
28
-	runSimpleContainer(ctx, t, request.NewAPIClient(t), name, func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
29
-		config.Cmd = []string{"true"}
30
-		hostConfig.Resources.CpusetCpus = "0"
31
-	})
28
+	container.Run(t, ctx, request.NewAPIClient(t), container.WithName(name),
29
+		container.WithCmd("true"),
30
+		func(c *container.TestContainerConfig) {
31
+			c.HostConfig.Resources.CpusetCpus = "0"
32
+		},
33
+	)
32 34
 	poll.WaitOn(t, containerIsInState(ctx, client, name, "exited"), poll.WithDelay(100*time.Millisecond))
33 35
 
34 36
 	_, body, err := client.ContainerInspectWithRaw(ctx, name, false)
... ...
@@ -5,11 +5,9 @@ import (
5 5
 	"testing"
6 6
 	"time"
7 7
 
8
-	"github.com/docker/docker/api/types"
9
-	"github.com/docker/docker/api/types/container"
10
-	"github.com/docker/docker/api/types/network"
11
-	"github.com/docker/docker/api/types/strslice"
8
+	containertypes "github.com/docker/docker/api/types/container"
12 9
 	"github.com/docker/docker/client"
10
+	"github.com/docker/docker/integration/internal/container"
13 11
 	"github.com/docker/docker/integration/internal/request"
14 12
 	"github.com/gotestyourself/gotestyourself/poll"
15 13
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -20,25 +18,15 @@ func TestKillContainerInvalidSignal(t *testing.T) {
20 20
 	defer setupTest(t)()
21 21
 	client := request.NewAPIClient(t)
22 22
 	ctx := context.Background()
23
-	c, err := client.ContainerCreate(ctx,
24
-		&container.Config{
25
-			Image: "busybox",
26
-			Cmd:   strslice.StrSlice([]string{"top"}),
27
-		},
28
-		&container.HostConfig{},
29
-		&network.NetworkingConfig{},
30
-		"")
31
-	require.NoError(t, err)
32
-	err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
33
-	require.NoError(t, err)
23
+	id := container.Run(t, ctx, client)
34 24
 
35
-	err = client.ContainerKill(ctx, c.ID, "0")
25
+	err := client.ContainerKill(ctx, id, "0")
36 26
 	require.EqualError(t, err, "Error response from daemon: Invalid signal: 0")
37
-	poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond))
27
+	poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
38 28
 
39
-	err = client.ContainerKill(ctx, c.ID, "SIG42")
29
+	err = client.ContainerKill(ctx, id, "SIG42")
40 30
 	require.EqualError(t, err, "Error response from daemon: Invalid signal: SIG42")
41
-	poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond))
31
+	poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
42 32
 }
43 33
 
44 34
 func TestKillContainer(t *testing.T) {
... ...
@@ -71,21 +59,11 @@ func TestKillContainer(t *testing.T) {
71 71
 		tc := tc
72 72
 		t.Run(tc.doc, func(t *testing.T) {
73 73
 			ctx := context.Background()
74
-			c, err := client.ContainerCreate(ctx,
75
-				&container.Config{
76
-					Image: "busybox",
77
-					Cmd:   strslice.StrSlice([]string{"top"}),
78
-				},
79
-				&container.HostConfig{},
80
-				&network.NetworkingConfig{},
81
-				"")
82
-			require.NoError(t, err)
83
-			err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
84
-			require.NoError(t, err)
85
-			err = client.ContainerKill(ctx, c.ID, tc.signal)
74
+			id := container.Run(t, ctx, client)
75
+			err := client.ContainerKill(ctx, id, tc.signal)
86 76
 			require.NoError(t, err)
87 77
 
88
-			poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond))
78
+			poll.WaitOn(t, containerIsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
89 79
 		})
90 80
 	}
91 81
 }
... ...
@@ -116,25 +94,16 @@ func TestKillWithStopSignalAndRestartPolicies(t *testing.T) {
116 116
 		tc := tc
117 117
 		t.Run(tc.doc, func(t *testing.T) {
118 118
 			ctx := context.Background()
119
-			c, err := client.ContainerCreate(ctx,
120
-				&container.Config{
121
-					Image:      "busybox",
122
-					Cmd:        strslice.StrSlice([]string{"top"}),
123
-					StopSignal: tc.stopsignal,
124
-				},
125
-				&container.HostConfig{
126
-					RestartPolicy: container.RestartPolicy{
127
-						Name: "always",
128
-					}},
129
-				&network.NetworkingConfig{},
130
-				"")
131
-			require.NoError(t, err)
132
-			err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
133
-			require.NoError(t, err)
134
-			err = client.ContainerKill(ctx, c.ID, "TERM")
119
+			id := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
120
+				c.Config.StopSignal = tc.stopsignal
121
+				c.HostConfig.RestartPolicy = containertypes.RestartPolicy{
122
+					Name: "always",
123
+				}
124
+			})
125
+			err := client.ContainerKill(ctx, id, "TERM")
135 126
 			require.NoError(t, err)
136 127
 
137
-			poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond))
128
+			poll.WaitOn(t, containerIsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
138 129
 		})
139 130
 	}
140 131
 }
... ...
@@ -144,16 +113,8 @@ func TestKillStoppedContainer(t *testing.T) {
144 144
 	defer setupTest(t)()
145 145
 	ctx := context.Background()
146 146
 	client := request.NewAPIClient(t)
147
-	c, err := client.ContainerCreate(ctx,
148
-		&container.Config{
149
-			Image: "busybox",
150
-			Cmd:   strslice.StrSlice([]string{"top"}),
151
-		},
152
-		&container.HostConfig{},
153
-		&network.NetworkingConfig{},
154
-		"")
155
-	require.NoError(t, err)
156
-	err = client.ContainerKill(ctx, c.ID, "SIGKILL")
147
+	id := container.Create(t, ctx, client)
148
+	err := client.ContainerKill(ctx, id, "SIGKILL")
157 149
 	require.Error(t, err)
158 150
 	require.Contains(t, err.Error(), "is not running")
159 151
 }
... ...
@@ -163,16 +124,8 @@ func TestKillStoppedContainerAPIPre120(t *testing.T) {
163 163
 	defer setupTest(t)()
164 164
 	ctx := context.Background()
165 165
 	client := request.NewAPIClient(t, client.WithVersion("1.19"))
166
-	c, err := client.ContainerCreate(ctx,
167
-		&container.Config{
168
-			Image: "busybox",
169
-			Cmd:   strslice.StrSlice([]string{"top"}),
170
-		},
171
-		&container.HostConfig{},
172
-		&network.NetworkingConfig{},
173
-		"")
174
-	require.NoError(t, err)
175
-	err = client.ContainerKill(ctx, c.ID, "SIGKILL")
166
+	id := container.Create(t, ctx, client)
167
+	err := client.ContainerKill(ctx, id, "SIGKILL")
176 168
 	require.NoError(t, err)
177 169
 }
178 170
 
... ...
@@ -184,12 +137,12 @@ func TestKillDifferentUserContainer(t *testing.T) {
184 184
 	ctx := context.Background()
185 185
 	client := request.NewAPIClient(t, client.WithVersion("1.19"))
186 186
 
187
-	cID := runSimpleContainer(ctx, t, client, "", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
188
-		config.User = "daemon"
187
+	id := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
188
+		c.Config.User = "daemon"
189 189
 	})
190
-	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
190
+	poll.WaitOn(t, containerIsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
191 191
 
192
-	err := client.ContainerKill(ctx, cID, "SIGKILL")
192
+	err := client.ContainerKill(ctx, id, "SIGKILL")
193 193
 	require.NoError(t, err)
194
-	poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
194
+	poll.WaitOn(t, containerIsInState(ctx, client, id, "exited"), poll.WithDelay(100*time.Millisecond))
195 195
 }
... ...
@@ -1,17 +1,11 @@
1 1
 package container // import "github.com/docker/docker/integration/container"
2 2
 
3 3
 import (
4
-	"context"
5 4
 	"fmt"
6 5
 	"os"
7 6
 	"testing"
8 7
 
9
-	"github.com/docker/docker/api/types"
10
-	"github.com/docker/docker/api/types/container"
11
-	"github.com/docker/docker/api/types/network"
12
-	"github.com/docker/docker/client"
13 8
 	"github.com/docker/docker/internal/test/environment"
14
-	"github.com/stretchr/testify/require"
15 9
 )
16 10
 
17 11
 var testEnv *environment.Execution
... ...
@@ -37,32 +31,3 @@ func setupTest(t *testing.T) func() {
37 37
 	environment.ProtectAll(t, testEnv)
38 38
 	return func() { testEnv.Clean(t) }
39 39
 }
40
-
41
-type containerConstructor func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig)
42
-
43
-func createSimpleContainer(ctx context.Context, t *testing.T, client client.APIClient, name string, f ...containerConstructor) string {
44
-	config := &container.Config{
45
-		Cmd:   []string{"top"},
46
-		Image: "busybox",
47
-	}
48
-	hostConfig := &container.HostConfig{}
49
-	networkingConfig := &network.NetworkingConfig{}
50
-
51
-	for _, fn := range f {
52
-		fn(config, hostConfig, networkingConfig)
53
-	}
54
-
55
-	c, err := client.ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
56
-	require.NoError(t, err)
57
-
58
-	return c.ID
59
-}
60
-
61
-func runSimpleContainer(ctx context.Context, t *testing.T, client client.APIClient, name string, f ...containerConstructor) string {
62
-	cID := createSimpleContainer(ctx, t, client, name, f...)
63
-
64
-	err := client.ContainerStart(ctx, cID, types.ContainerStartOptions{})
65
-	require.NoError(t, err)
66
-
67
-	return cID
68
-}
... ...
@@ -6,8 +6,8 @@ import (
6 6
 	"time"
7 7
 
8 8
 	"github.com/docker/docker/api/types"
9
-	"github.com/docker/docker/api/types/container"
10 9
 	"github.com/docker/docker/api/types/network"
10
+	"github.com/docker/docker/integration/internal/container"
11 11
 	"github.com/docker/docker/integration/internal/request"
12 12
 	"github.com/docker/docker/internal/testutil"
13 13
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -26,23 +26,18 @@ func TestRenameLinkedContainer(t *testing.T) {
26 26
 	ctx := context.Background()
27 27
 	client := request.NewAPIClient(t)
28 28
 
29
-	aID := runSimpleContainer(ctx, t, client, "a0")
30
-
31
-	bID := runSimpleContainer(ctx, t, client, "b0", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
32
-		hostConfig.Links = []string{"a0"}
33
-	})
29
+	aID := container.Run(t, ctx, client, container.WithName("a0"))
30
+	bID := container.Run(t, ctx, client, container.WithName("b0"), container.WithLinks("a0"))
34 31
 
35 32
 	err := client.ContainerRename(ctx, aID, "a1")
36 33
 	require.NoError(t, err)
37 34
 
38
-	runSimpleContainer(ctx, t, client, "a0")
35
+	container.Run(t, ctx, client, container.WithName("a0"))
39 36
 
40 37
 	err = client.ContainerRemove(ctx, bID, types.ContainerRemoveOptions{Force: true})
41 38
 	require.NoError(t, err)
42 39
 
43
-	bID = runSimpleContainer(ctx, t, client, "b0", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
44
-		hostConfig.Links = []string{"a0"}
45
-	})
40
+	bID = container.Run(t, ctx, client, container.WithName("b0"), container.WithLinks("a0"))
46 41
 
47 42
 	inspect, err := client.ContainerInspect(ctx, bID)
48 43
 	require.NoError(t, err)
... ...
@@ -55,9 +50,7 @@ func TestRenameStoppedContainer(t *testing.T) {
55 55
 	client := request.NewAPIClient(t)
56 56
 
57 57
 	oldName := "first_name"
58
-	cID := runSimpleContainer(ctx, t, client, oldName, func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
59
-		config.Cmd = []string{"sh"}
60
-	})
58
+	cID := container.Run(t, ctx, client, container.WithName(oldName), container.WithCmd("sh"))
61 59
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
62 60
 
63 61
 	inspect, err := client.ContainerInspect(ctx, cID)
... ...
@@ -79,7 +72,7 @@ func TestRenameRunningContainerAndReuse(t *testing.T) {
79 79
 	client := request.NewAPIClient(t)
80 80
 
81 81
 	oldName := "first_name"
82
-	cID := runSimpleContainer(ctx, t, client, oldName)
82
+	cID := container.Run(t, ctx, client, container.WithName(oldName))
83 83
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
84 84
 
85 85
 	newName := "new_name" + stringid.GenerateNonCryptoID()
... ...
@@ -93,7 +86,7 @@ func TestRenameRunningContainerAndReuse(t *testing.T) {
93 93
 	_, err = client.ContainerInspect(ctx, oldName)
94 94
 	testutil.ErrorContains(t, err, "No such container: "+oldName)
95 95
 
96
-	cID = runSimpleContainer(ctx, t, client, oldName)
96
+	cID = container.Run(t, ctx, client, container.WithName(oldName))
97 97
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
98 98
 
99 99
 	inspect, err = client.ContainerInspect(ctx, cID)
... ...
@@ -107,7 +100,7 @@ func TestRenameInvalidName(t *testing.T) {
107 107
 	client := request.NewAPIClient(t)
108 108
 
109 109
 	oldName := "first_name"
110
-	cID := runSimpleContainer(ctx, t, client, oldName)
110
+	cID := container.Run(t, ctx, client, container.WithName(oldName))
111 111
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
112 112
 
113 113
 	err := client.ContainerRename(ctx, oldName, "new:invalid")
... ...
@@ -132,11 +125,11 @@ func TestRenameAnonymousContainer(t *testing.T) {
132 132
 
133 133
 	_, err := client.NetworkCreate(ctx, "network1", types.NetworkCreate{})
134 134
 	require.NoError(t, err)
135
-	cID := createSimpleContainer(ctx, t, client, "", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
136
-		networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
135
+	cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
136
+		c.NetworkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
137 137
 			"network1": {},
138 138
 		}
139
-		hostConfig.NetworkMode = "network1"
139
+		c.HostConfig.NetworkMode = "network1"
140 140
 	})
141 141
 	err = client.ContainerRename(ctx, cID, "container1")
142 142
 	require.NoError(t, err)
... ...
@@ -149,13 +142,12 @@ func TestRenameAnonymousContainer(t *testing.T) {
149 149
 	if testEnv.OSType == "windows" {
150 150
 		count = "-n"
151 151
 	}
152
-	cID = runSimpleContainer(ctx, t, client, "", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
153
-		networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
152
+	cID = container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
153
+		c.NetworkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
154 154
 			"network1": {},
155 155
 		}
156
-		hostConfig.NetworkMode = "network1"
157
-		config.Cmd = []string{"ping", count, "1", "container1"}
158
-	})
156
+		c.HostConfig.NetworkMode = "network1"
157
+	}, container.WithCmd("ping", count, "1", "container1"))
159 158
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
160 159
 
161 160
 	inspect, err := client.ContainerInspect(ctx, cID)
... ...
@@ -169,7 +161,7 @@ func TestRenameContainerWithSameName(t *testing.T) {
169 169
 	ctx := context.Background()
170 170
 	client := request.NewAPIClient(t)
171 171
 
172
-	cID := runSimpleContainer(ctx, t, client, "old")
172
+	cID := container.Run(t, ctx, client, container.WithName("old"))
173 173
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
174 174
 	err := client.ContainerRename(ctx, "old", "old")
175 175
 	testutil.ErrorContains(t, err, "Renaming a container with the same name")
... ...
@@ -189,12 +181,10 @@ func TestRenameContainerWithLinkedContainer(t *testing.T) {
189 189
 	ctx := context.Background()
190 190
 	client := request.NewAPIClient(t)
191 191
 
192
-	db1ID := runSimpleContainer(ctx, t, client, "db1")
192
+	db1ID := container.Run(t, ctx, client, container.WithName("db1"))
193 193
 	poll.WaitOn(t, containerIsInState(ctx, client, db1ID, "running"), poll.WithDelay(100*time.Millisecond))
194 194
 
195
-	app1ID := runSimpleContainer(ctx, t, client, "app1", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
196
-		hostConfig.Links = []string{"db1:/mysql"}
197
-	})
195
+	app1ID := container.Run(t, ctx, client, container.WithName("app1"), container.WithLinks("db1:/mysql"))
198 196
 	poll.WaitOn(t, containerIsInState(ctx, client, app1ID, "running"), poll.WithDelay(100*time.Millisecond))
199 197
 
200 198
 	err := client.ContainerRename(ctx, "app1", "app2")
... ...
@@ -7,9 +7,8 @@ import (
7 7
 	"time"
8 8
 
9 9
 	"github.com/docker/docker/api/types"
10
-	"github.com/docker/docker/api/types/container"
11
-	"github.com/docker/docker/api/types/network"
12 10
 	req "github.com/docker/docker/integration-cli/request"
11
+	"github.com/docker/docker/integration/internal/container"
13 12
 	"github.com/docker/docker/integration/internal/request"
14 13
 	"github.com/docker/docker/internal/testutil"
15 14
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -22,7 +21,7 @@ func TestResize(t *testing.T) {
22 22
 	client := request.NewAPIClient(t)
23 23
 	ctx := context.Background()
24 24
 
25
-	cID := runSimpleContainer(ctx, t, client, "")
25
+	cID := container.Run(t, ctx, client)
26 26
 
27 27
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
28 28
 
... ...
@@ -38,7 +37,7 @@ func TestResizeWithInvalidSize(t *testing.T) {
38 38
 	client := request.NewAPIClient(t)
39 39
 	ctx := context.Background()
40 40
 
41
-	cID := runSimpleContainer(ctx, t, client, "")
41
+	cID := container.Run(t, ctx, client)
42 42
 
43 43
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
44 44
 
... ...
@@ -53,9 +52,7 @@ func TestResizeWhenContainerNotStarted(t *testing.T) {
53 53
 	client := request.NewAPIClient(t)
54 54
 	ctx := context.Background()
55 55
 
56
-	cID := runSimpleContainer(ctx, t, client, "", func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) {
57
-		config.Cmd = []string{"echo"}
58
-	})
56
+	cID := container.Run(t, ctx, client, container.WithCmd("echo"))
59 57
 
60 58
 	poll.WaitOn(t, containerIsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
61 59
 
62 60
new file mode 100644
... ...
@@ -0,0 +1,54 @@
0
+package container
1
+
2
+import (
3
+	"context"
4
+	"testing"
5
+
6
+	"github.com/docker/docker/api/types"
7
+	"github.com/docker/docker/api/types/container"
8
+	"github.com/docker/docker/api/types/network"
9
+	"github.com/docker/docker/client"
10
+	"github.com/stretchr/testify/require"
11
+)
12
+
13
+// TestContainerConfig holds container configuration struct that
14
+// are used in api calls.
15
+type TestContainerConfig struct {
16
+	Name             string
17
+	Config           *container.Config
18
+	HostConfig       *container.HostConfig
19
+	NetworkingConfig *network.NetworkingConfig
20
+}
21
+
22
+// Create creates a container with the specified options
23
+func Create(t *testing.T, ctx context.Context, client client.APIClient, ops ...func(*TestContainerConfig)) string { // nolint: golint
24
+	t.Helper()
25
+	config := &TestContainerConfig{
26
+		Config: &container.Config{
27
+			Image: "busybox",
28
+			Cmd:   []string{"top"},
29
+		},
30
+		HostConfig:       &container.HostConfig{},
31
+		NetworkingConfig: &network.NetworkingConfig{},
32
+	}
33
+
34
+	for _, op := range ops {
35
+		op(config)
36
+	}
37
+
38
+	c, err := client.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Name)
39
+	require.NoError(t, err)
40
+
41
+	return c.ID
42
+}
43
+
44
+// Run creates and start a container with the specified options
45
+func Run(t *testing.T, ctx context.Context, client client.APIClient, ops ...func(*TestContainerConfig)) string { // nolint: golint
46
+	t.Helper()
47
+	id := Create(t, ctx, client, ops...)
48
+
49
+	err := client.ContainerStart(ctx, id, types.ContainerStartOptions{})
50
+	require.NoError(t, err)
51
+
52
+	return id
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+package container
1
+
2
+import "github.com/docker/docker/api/types/strslice"
3
+
4
+// WithName sets the name of the container
5
+func WithName(name string) func(*TestContainerConfig) {
6
+	return func(c *TestContainerConfig) {
7
+		c.Name = name
8
+	}
9
+}
10
+
11
+// WithLinks sets the links of the container
12
+func WithLinks(links ...string) func(*TestContainerConfig) {
13
+	return func(c *TestContainerConfig) {
14
+		c.HostConfig.Links = links
15
+	}
16
+}
17
+
18
+// WithCmd sets the comannds of the container
19
+func WithCmd(cmds ...string) func(*TestContainerConfig) {
20
+	return func(c *TestContainerConfig) {
21
+		c.Config.Cmd = strslice.StrSlice(cmds)
22
+	}
23
+}