github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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/dockercli/trusted:latest", privateRegistryURL) 305 // tag the image and upload it to the private registry 306 dockerCmd(c, "tag", "busybox", repoName) 307 dockerCmd(c, "push", repoName) 308 dockerCmd(c, "rmi", repoName) 309 310 // Try trusted create on untrusted tag 311 createCmd := exec.Command(dockerBinary, "create", repoName) 312 s.trustedCmd(createCmd) 313 out, _, err := runCommandWithOutput(createCmd) 314 c.Assert(err, check.Not(check.IsNil)) 315 c.Assert(string(out), checker.Contains, "does not have trust data for", check.Commentf("Missing expected output on trusted create:\n%s", out)) 316 317 } 318 319 func (s *DockerTrustSuite) TestTrustedIsolatedCreate(c *check.C) { 320 repoName := s.setupTrustedImage(c, "trusted-isolated-create") 321 322 // Try create 323 createCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated-create", "create", repoName) 324 s.trustedCmd(createCmd) 325 out, _, err := runCommandWithOutput(createCmd) 326 c.Assert(err, check.IsNil) 327 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out)) 328 329 dockerCmd(c, "rmi", repoName) 330 } 331 332 func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) { 333 c.Skip("Currently changes system time, causing instability") 334 repoName := s.setupTrustedImage(c, "trusted-create-expired") 335 336 // Certificates have 10 years of expiration 337 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 338 339 runAtDifferentDate(elevenYearsFromNow, func() { 340 // Try create 341 createCmd := exec.Command(dockerBinary, "create", repoName) 342 s.trustedCmd(createCmd) 343 out, _, err := runCommandWithOutput(createCmd) 344 c.Assert(err, check.Not(check.IsNil)) 345 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)) 346 }) 347 348 runAtDifferentDate(elevenYearsFromNow, func() { 349 // Try create 350 createCmd := exec.Command(dockerBinary, "create", "--disable-content-trust", repoName) 351 s.trustedCmd(createCmd) 352 out, _, err := runCommandWithOutput(createCmd) 353 c.Assert(err, check.Not(check.IsNil)) 354 c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out)) 355 356 }) 357 } 358 359 func (s *DockerTrustSuite) TestTrustedCreateFromBadTrustServer(c *check.C) { 360 repoName := fmt.Sprintf("%v/dockerclievilcreate/trusted:latest", privateRegistryURL) 361 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 362 c.Assert(err, check.IsNil) 363 364 // tag the image and upload it to the private registry 365 dockerCmd(c, "tag", "busybox", repoName) 366 367 pushCmd := exec.Command(dockerBinary, "push", repoName) 368 s.trustedCmd(pushCmd) 369 out, _, err := runCommandWithOutput(pushCmd) 370 c.Assert(err, check.IsNil) 371 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out)) 372 373 dockerCmd(c, "rmi", repoName) 374 375 // Try create 376 createCmd := exec.Command(dockerBinary, "create", repoName) 377 s.trustedCmd(createCmd) 378 out, _, err = runCommandWithOutput(createCmd) 379 c.Assert(err, check.IsNil) 380 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf("Missing expected output on trusted push:\n%s", out)) 381 382 dockerCmd(c, "rmi", repoName) 383 384 // Kill the notary server, start a new "evil" one. 385 s.not.Close() 386 s.not, err = newTestNotary(c) 387 c.Assert(err, check.IsNil) 388 389 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 390 // tag an image and upload it to the private registry 391 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 392 393 // Push up to the new server 394 pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName) 395 s.trustedCmd(pushCmd) 396 out, _, err = runCommandWithOutput(pushCmd) 397 c.Assert(err, check.IsNil) 398 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out)) 399 400 // Now, try creating with the original client from this new trust server. This should fail. 401 createCmd = exec.Command(dockerBinary, "create", repoName) 402 s.trustedCmd(createCmd) 403 out, _, err = runCommandWithOutput(createCmd) 404 c.Assert(err, check.Not(check.IsNil)) 405 c.Assert(string(out), checker.Contains, "failed to validate data with current trusted certificates", check.Commentf("Missing expected output on trusted push:\n%s", out)) 406 407 } 408 409 func (s *DockerSuite) TestCreateStopSignal(c *check.C) { 410 name := "test_create_stop_signal" 411 dockerCmd(c, "create", "--name", name, "--stop-signal", "9", "busybox") 412 413 res, err := inspectFieldJSON(name, "Config.StopSignal") 414 c.Assert(err, check.IsNil) 415 c.Assert(res, checker.Contains, "9") 416 417 }