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