github.com/ruphin/docker@v1.10.1/integration-cli/docker_cli_create_test.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "time" 10 11 "os/exec" 12 13 "io/ioutil" 14 15 "github.com/docker/docker/pkg/integration/checker" 16 "github.com/docker/docker/pkg/stringid" 17 "github.com/docker/go-connections/nat" 18 "github.com/go-check/check" 19 ) 20 21 // Make sure we can create a simple container with some args 22 func (s *DockerSuite) TestCreateArgs(c *check.C) { 23 testRequires(c, DaemonIsLinux) 24 out, _ := dockerCmd(c, "create", "busybox", "command", "arg1", "arg2", "arg with space") 25 26 cleanedContainerID := strings.TrimSpace(out) 27 28 out, _ = dockerCmd(c, "inspect", cleanedContainerID) 29 30 containers := []struct { 31 ID string 32 Created time.Time 33 Path string 34 Args []string 35 Image string 36 }{} 37 38 err := json.Unmarshal([]byte(out), &containers) 39 c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err)) 40 c.Assert(containers, checker.HasLen, 1) 41 42 cont := containers[0] 43 c.Assert(string(cont.Path), checker.Equals, "command", check.Commentf("Unexpected container path. Expected command, received: %s", cont.Path)) 44 45 b := false 46 expected := []string{"arg1", "arg2", "arg with space"} 47 for i, arg := range expected { 48 if arg != cont.Args[i] { 49 b = true 50 break 51 } 52 } 53 if len(cont.Args) != len(expected) || b { 54 c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args) 55 } 56 57 } 58 59 // Make sure we can set hostconfig options too 60 func (s *DockerSuite) TestCreateHostConfig(c *check.C) { 61 testRequires(c, DaemonIsLinux) 62 out, _ := dockerCmd(c, "create", "-P", "busybox", "echo") 63 64 cleanedContainerID := strings.TrimSpace(out) 65 66 out, _ = dockerCmd(c, "inspect", cleanedContainerID) 67 68 containers := []struct { 69 HostConfig *struct { 70 PublishAllPorts bool 71 } 72 }{} 73 74 err := json.Unmarshal([]byte(out), &containers) 75 c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err)) 76 c.Assert(containers, checker.HasLen, 1) 77 78 cont := containers[0] 79 c.Assert(cont.HostConfig, check.NotNil, check.Commentf("Expected HostConfig, got none")) 80 c.Assert(cont.HostConfig.PublishAllPorts, check.NotNil, check.Commentf("Expected PublishAllPorts, got false")) 81 } 82 83 func (s *DockerSuite) TestCreateWithPortRange(c *check.C) { 84 testRequires(c, DaemonIsLinux) 85 out, _ := dockerCmd(c, "create", "-p", "3300-3303:3300-3303/tcp", "busybox", "echo") 86 87 cleanedContainerID := strings.TrimSpace(out) 88 89 out, _ = dockerCmd(c, "inspect", cleanedContainerID) 90 91 containers := []struct { 92 HostConfig *struct { 93 PortBindings map[nat.Port][]nat.PortBinding 94 } 95 }{} 96 err := json.Unmarshal([]byte(out), &containers) 97 c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err)) 98 c.Assert(containers, checker.HasLen, 1) 99 100 cont := containers[0] 101 102 c.Assert(cont.HostConfig, check.NotNil, check.Commentf("Expected HostConfig, got none")) 103 c.Assert(cont.HostConfig.PortBindings, checker.HasLen, 4, check.Commentf("Expected 4 ports bindings, got %d", len(cont.HostConfig.PortBindings))) 104 105 for k, v := range cont.HostConfig.PortBindings { 106 c.Assert(v, checker.HasLen, 1, check.Commentf("Expected 1 ports binding, for the port %s but found %s", k, v)) 107 c.Assert(k.Port(), checker.Equals, v[0].HostPort, check.Commentf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort)) 108 109 } 110 111 } 112 113 func (s *DockerSuite) TestCreateWithiLargePortRange(c *check.C) { 114 testRequires(c, DaemonIsLinux) 115 out, _ := dockerCmd(c, "create", "-p", "1-65535:1-65535/tcp", "busybox", "echo") 116 117 cleanedContainerID := strings.TrimSpace(out) 118 119 out, _ = dockerCmd(c, "inspect", cleanedContainerID) 120 121 containers := []struct { 122 HostConfig *struct { 123 PortBindings map[nat.Port][]nat.PortBinding 124 } 125 }{} 126 127 err := json.Unmarshal([]byte(out), &containers) 128 c.Assert(err, check.IsNil, check.Commentf("Error inspecting the container: %s", err)) 129 c.Assert(containers, checker.HasLen, 1) 130 131 cont := containers[0] 132 c.Assert(cont.HostConfig, check.NotNil, check.Commentf("Expected HostConfig, got none")) 133 c.Assert(cont.HostConfig.PortBindings, checker.HasLen, 65535) 134 135 for k, v := range cont.HostConfig.PortBindings { 136 c.Assert(v, checker.HasLen, 1) 137 c.Assert(k.Port(), checker.Equals, v[0].HostPort, check.Commentf("Expected host port %s to match published port %s", k.Port(), v[0].HostPort)) 138 } 139 140 } 141 142 // "test123" should be printed by docker create + start 143 func (s *DockerSuite) TestCreateEchoStdout(c *check.C) { 144 testRequires(c, DaemonIsLinux) 145 146 out, _ := dockerCmd(c, "create", "busybox", "echo", "test123") 147 148 cleanedContainerID := strings.TrimSpace(out) 149 150 out, _ = dockerCmd(c, "start", "-ai", cleanedContainerID) 151 c.Assert(out, checker.Equals, "test123\n", check.Commentf("container should've printed 'test123', got %q", out)) 152 153 } 154 155 func (s *DockerSuite) TestCreateVolumesCreated(c *check.C) { 156 testRequires(c, DaemonIsLinux) 157 testRequires(c, SameHostDaemon) 158 159 name := "test_create_volume" 160 dockerCmd(c, "create", "--name", name, "-v", "/foo", "busybox") 161 162 dir, err := inspectMountSourceField(name, "/foo") 163 c.Assert(err, check.IsNil, check.Commentf("Error getting volume host path: %q", err)) 164 165 if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { 166 c.Fatalf("Volume was not created") 167 } 168 if err != nil { 169 c.Fatalf("Error statting volume host path: %q", err) 170 } 171 172 } 173 174 func (s *DockerSuite) TestCreateLabels(c *check.C) { 175 testRequires(c, DaemonIsLinux) 176 name := "test_create_labels" 177 expected := map[string]string{"k1": "v1", "k2": "v2"} 178 dockerCmd(c, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox") 179 180 actual := make(map[string]string) 181 err := inspectFieldAndMarshall(name, "Config.Labels", &actual) 182 c.Assert(err, check.IsNil) 183 184 if !reflect.DeepEqual(expected, actual) { 185 c.Fatalf("Expected %s got %s", expected, actual) 186 } 187 } 188 189 func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) { 190 testRequires(c, DaemonIsLinux) 191 imageName := "testcreatebuildlabel" 192 _, err := buildImage(imageName, 193 `FROM busybox 194 LABEL k1=v1 k2=v2`, 195 true) 196 197 c.Assert(err, check.IsNil) 198 199 name := "test_create_labels_from_image" 200 expected := map[string]string{"k2": "x", "k3": "v3", "k1": "v1"} 201 dockerCmd(c, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName) 202 203 actual := make(map[string]string) 204 err = inspectFieldAndMarshall(name, "Config.Labels", &actual) 205 c.Assert(err, check.IsNil) 206 207 if !reflect.DeepEqual(expected, actual) { 208 c.Fatalf("Expected %s got %s", expected, actual) 209 } 210 } 211 212 func (s *DockerSuite) TestCreateHostnameWithNumber(c *check.C) { 213 testRequires(c, DaemonIsLinux) 214 out, _ := dockerCmd(c, "run", "-h", "web.0", "busybox", "hostname") 215 c.Assert(strings.TrimSpace(out), checker.Equals, "web.0", check.Commentf("hostname not set, expected `web.0`, got: %s", out)) 216 217 } 218 219 func (s *DockerSuite) TestCreateRM(c *check.C) { 220 testRequires(c, DaemonIsLinux) 221 // Test to make sure we can 'rm' a new container that is in 222 // "Created" state, and has ever been run. Test "rm -f" too. 223 224 // create a container 225 out, _ := dockerCmd(c, "create", "busybox") 226 cID := strings.TrimSpace(out) 227 228 dockerCmd(c, "rm", cID) 229 230 // Now do it again so we can "rm -f" this time 231 out, _ = dockerCmd(c, "create", "busybox") 232 233 cID = strings.TrimSpace(out) 234 dockerCmd(c, "rm", "-f", cID) 235 } 236 237 func (s *DockerSuite) TestCreateModeIpcContainer(c *check.C) { 238 testRequires(c, DaemonIsLinux) 239 testRequires(c, SameHostDaemon, NotUserNamespace) 240 241 out, _ := dockerCmd(c, "create", "busybox") 242 id := strings.TrimSpace(out) 243 244 dockerCmd(c, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox") 245 } 246 247 func (s *DockerSuite) TestCreateByImageID(c *check.C) { 248 imageName := "testcreatebyimageid" 249 imageID, err := buildImage(imageName, 250 `FROM busybox 251 MAINTAINER dockerio`, 252 true) 253 if err != nil { 254 c.Fatal(err) 255 } 256 truncatedImageID := stringid.TruncateID(imageID) 257 258 dockerCmd(c, "create", imageID) 259 dockerCmd(c, "create", truncatedImageID) 260 dockerCmd(c, "create", fmt.Sprintf("%s:%s", imageName, truncatedImageID)) 261 262 // Ensure this fails 263 out, exit, _ := dockerCmdWithError("create", fmt.Sprintf("%s:%s", imageName, imageID)) 264 if exit == 0 { 265 c.Fatalf("expected non-zero exit code; received %d", exit) 266 } 267 268 if expected := "Error parsing reference"; !strings.Contains(out, expected) { 269 c.Fatalf(`Expected %q in output; got: %s`, expected, out) 270 } 271 272 out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", truncatedImageID)) 273 if exit == 0 { 274 c.Fatalf("expected non-zero exit code; received %d", exit) 275 } 276 277 if expected := "Unable to find image"; !strings.Contains(out, expected) { 278 c.Fatalf(`Expected %q in output; got: %s`, expected, out) 279 } 280 } 281 282 func (s *DockerTrustSuite) TestTrustedCreate(c *check.C) { 283 repoName := s.setupTrustedImage(c, "trusted-create") 284 285 // Try create 286 createCmd := exec.Command(dockerBinary, "create", repoName) 287 s.trustedCmd(createCmd) 288 out, _, err := runCommandWithOutput(createCmd) 289 c.Assert(err, check.IsNil) 290 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out)) 291 292 dockerCmd(c, "rmi", repoName) 293 294 // Try untrusted create to ensure we pushed the tag to the registry 295 createCmd = exec.Command(dockerBinary, "create", "--disable-content-trust=true", repoName) 296 s.trustedCmd(createCmd) 297 out, _, err = runCommandWithOutput(createCmd) 298 c.Assert(err, check.IsNil) 299 c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted create with --disable-content-trust:\n%s", out)) 300 301 } 302 303 func (s *DockerTrustSuite) TestUntrustedCreate(c *check.C) { 304 repoName := fmt.Sprintf("%v/dockercliuntrusted/createtest", privateRegistryURL) 305 withTagName := fmt.Sprintf("%s:latest", repoName) 306 // tag the image and upload it to the private registry 307 dockerCmd(c, "tag", "busybox", withTagName) 308 dockerCmd(c, "push", withTagName) 309 dockerCmd(c, "rmi", withTagName) 310 311 // Try trusted create on untrusted tag 312 createCmd := exec.Command(dockerBinary, "create", withTagName) 313 s.trustedCmd(createCmd) 314 out, _, err := runCommandWithOutput(createCmd) 315 c.Assert(err, check.Not(check.IsNil)) 316 c.Assert(string(out), checker.Contains, fmt.Sprintf("does not have trust data for %s", repoName), check.Commentf("Missing expected output on trusted create:\n%s", out)) 317 318 } 319 320 func (s *DockerTrustSuite) TestTrustedIsolatedCreate(c *check.C) { 321 repoName := s.setupTrustedImage(c, "trusted-isolated-create") 322 323 // Try create 324 createCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated-create", "create", repoName) 325 s.trustedCmd(createCmd) 326 out, _, err := runCommandWithOutput(createCmd) 327 c.Assert(err, check.IsNil) 328 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out)) 329 330 dockerCmd(c, "rmi", repoName) 331 } 332 333 func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) { 334 c.Skip("Currently changes system time, causing instability") 335 repoName := s.setupTrustedImage(c, "trusted-create-expired") 336 337 // Certificates have 10 years of expiration 338 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 339 340 runAtDifferentDate(elevenYearsFromNow, func() { 341 // Try create 342 createCmd := exec.Command(dockerBinary, "create", repoName) 343 s.trustedCmd(createCmd) 344 out, _, err := runCommandWithOutput(createCmd) 345 c.Assert(err, check.Not(check.IsNil)) 346 c.Assert(string(out), checker.Contains, "could not validate the path to a trusted root", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out)) 347 }) 348 349 runAtDifferentDate(elevenYearsFromNow, func() { 350 // Try create 351 createCmd := exec.Command(dockerBinary, "create", "--disable-content-trust", repoName) 352 s.trustedCmd(createCmd) 353 out, _, err := runCommandWithOutput(createCmd) 354 c.Assert(err, check.Not(check.IsNil)) 355 c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out)) 356 357 }) 358 } 359 360 func (s *DockerTrustSuite) TestTrustedCreateFromBadTrustServer(c *check.C) { 361 repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL) 362 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 363 c.Assert(err, check.IsNil) 364 365 // tag the image and upload it to the private registry 366 dockerCmd(c, "tag", "busybox", repoName) 367 368 pushCmd := exec.Command(dockerBinary, "push", repoName) 369 s.trustedCmd(pushCmd) 370 out, _, err := runCommandWithOutput(pushCmd) 371 c.Assert(err, check.IsNil) 372 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out)) 373 374 dockerCmd(c, "rmi", repoName) 375 376 // Try create 377 createCmd := exec.Command(dockerBinary, "create", repoName) 378 s.trustedCmd(createCmd) 379 out, _, err = runCommandWithOutput(createCmd) 380 c.Assert(err, check.IsNil) 381 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out)) 382 383 dockerCmd(c, "rmi", repoName) 384 385 // Kill the notary server, start a new "evil" one. 386 s.not.Close() 387 s.not, err = newTestNotary(c) 388 c.Assert(err, check.IsNil) 389 390 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 391 // tag an image and upload it to the private registry 392 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 393 394 // Push up to the new server 395 pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName) 396 s.trustedCmd(pushCmd) 397 out, _, err = runCommandWithOutput(pushCmd) 398 c.Assert(err, check.IsNil) 399 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out)) 400 401 // Now, try creating with the original client from this new trust server. This should fail. 402 createCmd = exec.Command(dockerBinary, "create", repoName) 403 s.trustedCmd(createCmd) 404 out, _, err = runCommandWithOutput(createCmd) 405 c.Assert(err, check.Not(check.IsNil)) 406 c.Assert(string(out), checker.Contains, "valid signatures did not meet threshold", check.Commentf("Missing expected output on trusted push:\n%s", out)) 407 408 } 409 410 func (s *DockerSuite) TestCreateStopSignal(c *check.C) { 411 name := "test_create_stop_signal" 412 dockerCmd(c, "create", "--name", name, "--stop-signal", "9", "busybox") 413 414 res, err := inspectFieldJSON(name, "Config.StopSignal") 415 c.Assert(err, check.IsNil) 416 c.Assert(res, checker.Contains, "9") 417 418 } 419 420 func (s *DockerSuite) TestCreateWithWorkdir(c *check.C) { 421 testRequires(c, DaemonIsLinux) 422 name := "foo" 423 dir := "/home/foo/bar" 424 dockerCmd(c, "create", "--name", name, "-w", dir, "busybox") 425 dockerCmd(c, "cp", fmt.Sprintf("%s:%s", name, dir), "/tmp") 426 }