github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration/container/create_test.go (about) 1 package container // import "github.com/docker/docker/integration/container" 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "strconv" 8 "testing" 9 "time" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/container" 13 "github.com/docker/docker/api/types/network" 14 ctr "github.com/docker/docker/integration/internal/container" 15 "github.com/docker/docker/oci" 16 "gotest.tools/assert" 17 is "gotest.tools/assert/cmp" 18 "gotest.tools/poll" 19 "gotest.tools/skip" 20 ) 21 22 func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) { 23 defer setupTest(t)() 24 client := testEnv.APIClient() 25 26 testCases := []struct { 27 doc string 28 image string 29 expectedError string 30 }{ 31 { 32 doc: "image and tag", 33 image: "test456:v1", 34 expectedError: "No such image: test456:v1", 35 }, 36 { 37 doc: "image no tag", 38 image: "test456", 39 expectedError: "No such image: test456", 40 }, 41 { 42 doc: "digest", 43 image: "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa", 44 expectedError: "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa", 45 }, 46 } 47 48 for _, tc := range testCases { 49 tc := tc 50 t.Run(tc.doc, func(t *testing.T) { 51 t.Parallel() 52 _, err := client.ContainerCreate(context.Background(), 53 &container.Config{Image: tc.image}, 54 &container.HostConfig{}, 55 &network.NetworkingConfig{}, 56 "", 57 ) 58 assert.Check(t, is.ErrorContains(err, tc.expectedError)) 59 }) 60 } 61 } 62 63 func TestCreateWithInvalidEnv(t *testing.T) { 64 defer setupTest(t)() 65 client := testEnv.APIClient() 66 67 testCases := []struct { 68 env string 69 expectedError string 70 }{ 71 { 72 env: "", 73 expectedError: "invalid environment variable:", 74 }, 75 { 76 env: "=", 77 expectedError: "invalid environment variable: =", 78 }, 79 { 80 env: "=foo", 81 expectedError: "invalid environment variable: =foo", 82 }, 83 } 84 85 for index, tc := range testCases { 86 tc := tc 87 t.Run(strconv.Itoa(index), func(t *testing.T) { 88 t.Parallel() 89 _, err := client.ContainerCreate(context.Background(), 90 &container.Config{ 91 Image: "busybox", 92 Env: []string{tc.env}, 93 }, 94 &container.HostConfig{}, 95 &network.NetworkingConfig{}, 96 "", 97 ) 98 assert.Check(t, is.ErrorContains(err, tc.expectedError)) 99 }) 100 } 101 } 102 103 // Test case for #30166 (target was not validated) 104 func TestCreateTmpfsMountsTarget(t *testing.T) { 105 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 106 107 defer setupTest(t)() 108 client := testEnv.APIClient() 109 110 testCases := []struct { 111 target string 112 expectedError string 113 }{ 114 { 115 target: ".", 116 expectedError: "mount path must be absolute", 117 }, 118 { 119 target: "foo", 120 expectedError: "mount path must be absolute", 121 }, 122 { 123 target: "/", 124 expectedError: "destination can't be '/'", 125 }, 126 { 127 target: "//", 128 expectedError: "destination can't be '/'", 129 }, 130 } 131 132 for _, tc := range testCases { 133 _, err := client.ContainerCreate(context.Background(), 134 &container.Config{ 135 Image: "busybox", 136 }, 137 &container.HostConfig{ 138 Tmpfs: map[string]string{tc.target: ""}, 139 }, 140 &network.NetworkingConfig{}, 141 "", 142 ) 143 assert.Check(t, is.ErrorContains(err, tc.expectedError)) 144 } 145 } 146 func TestCreateWithCustomMaskedPaths(t *testing.T) { 147 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 148 149 defer setupTest(t)() 150 client := testEnv.APIClient() 151 ctx := context.Background() 152 153 testCases := []struct { 154 maskedPaths []string 155 expected []string 156 }{ 157 { 158 maskedPaths: []string{}, 159 expected: []string{}, 160 }, 161 { 162 maskedPaths: nil, 163 expected: oci.DefaultSpec().Linux.MaskedPaths, 164 }, 165 { 166 maskedPaths: []string{"/proc/kcore", "/proc/keys"}, 167 expected: []string{"/proc/kcore", "/proc/keys"}, 168 }, 169 } 170 171 checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) { 172 _, b, err := client.ContainerInspectWithRaw(ctx, name, false) 173 assert.NilError(t, err) 174 175 var inspectJSON map[string]interface{} 176 err = json.Unmarshal(b, &inspectJSON) 177 assert.NilError(t, err) 178 179 cfg, ok := inspectJSON["HostConfig"].(map[string]interface{}) 180 assert.Check(t, is.Equal(true, ok), name) 181 182 maskedPaths, ok := cfg["MaskedPaths"].([]interface{}) 183 assert.Check(t, is.Equal(true, ok), name) 184 185 mps := []string{} 186 for _, mp := range maskedPaths { 187 mps = append(mps, mp.(string)) 188 } 189 190 assert.DeepEqual(t, expected, mps) 191 } 192 193 for i, tc := range testCases { 194 name := fmt.Sprintf("create-masked-paths-%d", i) 195 config := container.Config{ 196 Image: "busybox", 197 Cmd: []string{"true"}, 198 } 199 hc := container.HostConfig{} 200 if tc.maskedPaths != nil { 201 hc.MaskedPaths = tc.maskedPaths 202 } 203 204 // Create the container. 205 c, err := client.ContainerCreate(context.Background(), 206 &config, 207 &hc, 208 &network.NetworkingConfig{}, 209 name, 210 ) 211 assert.NilError(t, err) 212 213 checkInspect(t, ctx, name, tc.expected) 214 215 // Start the container. 216 err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) 217 assert.NilError(t, err) 218 219 poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond)) 220 221 checkInspect(t, ctx, name, tc.expected) 222 } 223 } 224 225 func TestCreateWithCustomReadonlyPaths(t *testing.T) { 226 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 227 228 defer setupTest(t)() 229 client := testEnv.APIClient() 230 ctx := context.Background() 231 232 testCases := []struct { 233 doc string 234 readonlyPaths []string 235 expected []string 236 }{ 237 { 238 readonlyPaths: []string{}, 239 expected: []string{}, 240 }, 241 { 242 readonlyPaths: nil, 243 expected: oci.DefaultSpec().Linux.ReadonlyPaths, 244 }, 245 { 246 readonlyPaths: []string{"/proc/asound", "/proc/bus"}, 247 expected: []string{"/proc/asound", "/proc/bus"}, 248 }, 249 } 250 251 checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) { 252 _, b, err := client.ContainerInspectWithRaw(ctx, name, false) 253 assert.NilError(t, err) 254 255 var inspectJSON map[string]interface{} 256 err = json.Unmarshal(b, &inspectJSON) 257 assert.NilError(t, err) 258 259 cfg, ok := inspectJSON["HostConfig"].(map[string]interface{}) 260 assert.Check(t, is.Equal(true, ok), name) 261 262 readonlyPaths, ok := cfg["ReadonlyPaths"].([]interface{}) 263 assert.Check(t, is.Equal(true, ok), name) 264 265 rops := []string{} 266 for _, rop := range readonlyPaths { 267 rops = append(rops, rop.(string)) 268 } 269 assert.DeepEqual(t, expected, rops) 270 } 271 272 for i, tc := range testCases { 273 name := fmt.Sprintf("create-readonly-paths-%d", i) 274 config := container.Config{ 275 Image: "busybox", 276 Cmd: []string{"true"}, 277 } 278 hc := container.HostConfig{} 279 if tc.readonlyPaths != nil { 280 hc.ReadonlyPaths = tc.readonlyPaths 281 } 282 283 // Create the container. 284 c, err := client.ContainerCreate(context.Background(), 285 &config, 286 &hc, 287 &network.NetworkingConfig{}, 288 name, 289 ) 290 assert.NilError(t, err) 291 292 checkInspect(t, ctx, name, tc.expected) 293 294 // Start the container. 295 err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) 296 assert.NilError(t, err) 297 298 poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond)) 299 300 checkInspect(t, ctx, name, tc.expected) 301 } 302 }