Esempio n. 1
0
func cleanContainers(c *check.C) *docker.Project {
	client, err := dockerclient.NewEnvClient()
	c.Assert(err, check.IsNil)

	filterArgs := filters.NewArgs()
	filterArgs, err = filters.ParseFlag(d.KermitLabelFilter, filterArgs)
	c.Assert(err, check.IsNil)

	containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{
		All:    true,
		Filter: filterArgs,
	})
	c.Assert(err, check.IsNil)

	for _, container := range containers {
		c.Logf("cleaning container %s…", container.ID)
		if err := client.ContainerRemove(context.Background(), container.ID, types.ContainerRemoveOptions{
			Force: true,
		}); err != nil {
			c.Errorf("Error while removing container %s : %v\n", container.ID, err)
		}
	}

	return docker.NewProject(client)
}
Esempio n. 2
0
// ensure tags cannot create ambiguity with image ids
func (s *DockerSuite) TestTagTruncationAmbiguity(c *check.C) {
	imageID, err := buildImage("notbusybox:latest",
		`FROM busybox
		MAINTAINER dockerio`,
		true)
	if err != nil {
		c.Fatal(err)
	}
	truncatedImageID := stringid.TruncateID(imageID)
	truncatedTag := fmt.Sprintf("notbusybox:%s", truncatedImageID)

	id := inspectField(c, truncatedTag, "Id")

	// Ensure inspect by image id returns image for image id
	c.Assert(id, checker.Equals, imageID)
	c.Logf("Built image: %s", imageID)

	// test setting tag fails
	_, _, err = dockerCmdWithError("tag", "busybox:latest", truncatedTag)
	if err != nil {
		c.Fatalf("Error tagging with an image id: %s", err)
	}

	id = inspectField(c, truncatedTag, "Id")

	// Ensure id is imageID and not busybox:latest
	c.Assert(id, checker.Not(checker.Equals), imageID)
}
func (s *DockerSwarmSuite) TestServiceLogs(c *check.C) {
	testRequires(c, ExperimentalDaemon)

	d := s.AddDaemon(c, true, true)

	// we have multiple services here for detecting the goroutine issue #28915
	services := map[string]string{
		"TestServiceLogs1": "hello1",
		"TestServiceLogs2": "hello2",
	}

	for name, message := range services {
		out, err := d.Cmd("service", "create", "--name", name, "busybox",
			"sh", "-c", fmt.Sprintf("echo %s; tail -f /dev/null", message))
		c.Assert(err, checker.IsNil)
		c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
	}

	// make sure task has been deployed.
	waitAndAssert(c, defaultReconciliationTimeout,
		d.CheckActiveContainerCount, checker.Equals, len(services))

	for name, message := range services {
		out, err := d.Cmd("service", "logs", name)
		c.Assert(err, checker.IsNil)
		c.Logf("log for %q: %q", name, out)
		c.Assert(out, checker.Contains, message)
	}
}
Esempio n. 4
0
func myLog(c *check.C, args ...interface{}) {
	if len(args) == 1 {
		c.Log(fmt.Sprintf("%s: %v\n", c.TestName(), args[0]))
		return
	}
	newArgs := make([]interface{}, len(args)-1)
	for i, a := range args[1:] {
		switch a := a.(type) {
		default:
			j, err := json.Marshal(a)
			if err == nil {
				newArgs[i] = fmt.Sprintf("%T: %s", a, j)
			} else {
				newArgs[i] = fmt.Sprintf("%s", a)
			}
		case bool:
			newArgs[i] = a
		case int:
			newArgs[i] = a
		case uint:
			newArgs[i] = a
		case uint64:
			newArgs[i] = a
		case string:
			newArgs[i] = a
		}
	}
	fmtStr := fmt.Sprintf("%s: %s\n", c.TestName(), args[0].(string))
	c.Logf(fmtStr, newArgs...)
}
Esempio n. 5
0
func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
	actualIDs := []string{}
	if out != "" {
		actualIDs = strings.Split(out[:len(out)-1], "\n")
	}
	sort.Strings(actualIDs)
	sort.Strings(expectedIDs)

	if len(actualIDs) != len(expectedIDs) {
		c.Fatalf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs)
	}
	if len(expectedIDs) > 0 {
		same := true
		for i := range expectedIDs {
			if actualIDs[i] != expectedIDs[i] {
				c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
				same = false
				break
			}
		}
		if !same {
			c.Fatalf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs)
		}
	}
}
func (s *DockerSuite) TestRunPrivilegedAllowedDevices(c *check.C) {
	testRequires(c, DaemonIsLinux, NotUserNamespace)

	file := "/sys/fs/cgroup/devices/devices.list"
	out, _ := dockerCmd(c, "run", "--privileged", "busybox", "cat", file)
	c.Logf("out: %q", out)
	c.Assert(strings.TrimSpace(out), checker.Equals, "a *:* rwm")
}
Esempio n. 7
0
// Stop will send a SIGINT every second and wait for the daemon to stop.
// If it times out, a SIGKILL is sent.
// Stop will not delete the daemon directory. If a purged daemon is needed,
// instantiate a new one with NewDaemon.
// If an error occurs while starting the daemon, the test will fail.
func (d *Daemon) Stop(c *check.C) {
	err := d.StopWithError()
	if err != nil {
		if err != errDaemonNotStarted {
			c.Fatalf("Error while stopping the daemon %s : %v", d.id, err)
		} else {
			c.Logf("Daemon %s is not started", d.id)
		}
	}
}
Esempio n. 8
0
func runDockerCp(c *check.C, src, dst string) (err error) {
	c.Logf("running `docker cp %s %s`", src, dst)

	args := []string{"cp", src, dst}

	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
	if err != nil {
		err = fmt.Errorf("error executing `docker cp` command: %s: %s", err, out)
	}

	return
}
Esempio n. 9
0
func startContainerGetOutput(c *check.C, cID string) (out string, err error) {
	c.Logf("running `docker start -a %s`", cID)

	args := []string{"start", "-a", cID}

	out, _, err = runCommandWithOutput(exec.Command(dockerBinary, args...))
	if err != nil {
		err = fmt.Errorf("error executing `docker start` command: %s: %s", err, out)
	}

	return
}
Esempio n. 10
0
func containerStartOutputEquals(c *check.C, cID, contents string) (err error) {
	c.Logf("checking that container %q start output contains %q\n", cID, contents)

	out, err := startContainerGetOutput(c, cID)
	if err != nil {
		return err
	}

	if out != contents {
		err = fmt.Errorf("output contents not equal - expected %q, got %q", contents, out)
	}

	return
}
func symlinkTargetEquals(c *check.C, symlink, expectedTarget string) (err error) {
	c.Logf("checking that the symlink %q points to %q\n", symlink, expectedTarget)

	actualTarget, err := os.Readlink(symlink)
	if err != nil {
		return err
	}

	if actualTarget != expectedTarget {
		return fmt.Errorf("symlink target points to %q not %q", actualTarget, expectedTarget)
	}

	return nil
}
Esempio n. 12
0
func cleanupExecRoot(c *check.C, execRoot string) {
	// Cleanup network namespaces in the exec root of this
	// daemon because this exec root is specific to this
	// daemon instance and has no chance of getting
	// cleaned up when a new daemon is instantiated with a
	// new exec root.
	netnsPath := filepath.Join(execRoot, "netns")
	filepath.Walk(netnsPath, func(path string, info os.FileInfo, err error) error {
		if err := syscall.Unmount(path, syscall.MNT_FORCE); err != nil {
			c.Logf("unmount of %s failed: %v", path, err)
		}
		os.Remove(path)
		return nil
	})
}
Esempio n. 13
0
func (s *DockerSwarmSuite) TearDownTest(c *check.C) {
	testRequires(c, DaemonIsLinux)
	s.daemonsLock.Lock()
	for _, d := range s.daemons {
		d.Stop()
		// raft state file is quite big (64MB) so remove it after every test
		walDir := filepath.Join(d.root, "swarm/raft/wal")
		if err := os.RemoveAll(walDir); err != nil {
			c.Logf("error removing %v: %v", walDir, err)
		}
	}
	s.daemons = nil
	s.daemonsLock.Unlock()

	s.portIndex = 0
	s.ds.TearDownTest(c)
}
Esempio n. 14
0
func fileContentEquals(c *check.C, filename, contents string) (err error) {
	c.Logf("checking that file %q contains %q\n", filename, contents)

	fileBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	expectedBytes, err := ioutil.ReadAll(strings.NewReader(contents))
	if err != nil {
		return
	}

	if !bytes.Equal(fileBytes, expectedBytes) {
		err = fmt.Errorf("file content not equal - expected %q, got %q", string(expectedBytes), string(fileBytes))
	}

	return
}
Esempio n. 15
0
// ensure tags cannot create ambiguity with image ids
func (s *DockerSuite) TestTagTruncationAmbiguity(c *check.C) {
	//testRequires(c, DaemonIsLinux)
	// Don't attempt to pull on Windows as not in hub. It's installed
	// as an image through .ensure-frozen-images-windows
	if daemonPlatform != "windows" {
		if err := pullImageIfNotExist("busybox:latest"); err != nil {
			c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
		}
	}
	imageID, err := buildImage("notbusybox:latest",
		`FROM busybox
		MAINTAINER dockerio`,
		true)
	if err != nil {
		c.Fatal(err)
	}
	truncatedImageID := stringid.TruncateID(imageID)
	truncatedTag := fmt.Sprintf("notbusybox:%s", truncatedImageID)

	id, err := inspectField(truncatedTag, "Id")
	if err != nil {
		c.Fatalf("Error inspecting by image id: %s", err)
	}

	// Ensure inspect by image id returns image for image id
	c.Assert(id, checker.Equals, imageID)
	c.Logf("Built image: %s", imageID)

	// test setting tag fails
	_, _, err = dockerCmdWithError("tag", "busybox:latest", truncatedTag)
	if err != nil {
		c.Fatalf("Error tagging with an image id: %s", err)
	}

	id, err = inspectField(truncatedTag, "Id")
	if err != nil {
		c.Fatalf("Error inspecting by image id: %s", err)
	}

	// Ensure id is imageID and not busybox:latest
	c.Assert(id, checker.Not(checker.Equals), imageID)
}
Esempio n. 16
0
func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
	actualIDs := []string{}
	if out != "" {
		actualIDs = strings.Split(out[:len(out)-1], "\n")
	}
	sort.Strings(actualIDs)
	sort.Strings(expectedIDs)

	c.Assert(actualIDs, checker.HasLen, len(expectedIDs), check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v:%v, got %v:%v", filterName, len(expectedIDs), expectedIDs, len(actualIDs), actualIDs))
	if len(expectedIDs) > 0 {
		same := true
		for i := range expectedIDs {
			if actualIDs[i] != expectedIDs[i] {
				c.Logf("%s, %s", actualIDs[i], expectedIDs[i])
				same = false
				break
			}
		}
		c.Assert(same, checker.Equals, true, check.Commentf("Expected filtered container(s) for %s ancestor filter to be %v, got %v", filterName, expectedIDs, actualIDs))
	}
}
Esempio n. 17
0
func (s *DockerSwarmSuite) TearDownTest(c *check.C) {
	testRequires(c, DaemonIsLinux)
	s.daemonsLock.Lock()
	for _, d := range s.daemons {
		if d != nil {
			d.Stop(c)
			// FIXME(vdemeester) should be handled by SwarmDaemon ?
			// raft state file is quite big (64MB) so remove it after every test
			walDir := filepath.Join(d.Root, "swarm/raft/wal")
			if err := os.RemoveAll(walDir); err != nil {
				c.Logf("error removing %v: %v", walDir, err)
			}

			d.CleanupExecRoot(c)
		}
	}
	s.daemons = nil
	s.daemonsLock.Unlock()

	s.portIndex = 0
	s.ds.TearDownTest(c)
}
Esempio n. 18
0
func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
	testRequires(c, DaemonIsLinux)
	// Make sure main help text fits within 80 chars and that
	// on non-windows system we use ~ when possible (to shorten things).
	// Test for HOME set to its default value and set to "/" on linux
	// Yes on windows setting up an array and looping (right now) isn't
	// necessary because we just have one value, but we'll need the
	// array/loop on linux so we might as well set it up so that we can
	// test any number of home dirs later on and all we need to do is
	// modify the array - the rest of the testing infrastructure should work
	homes := []string{homedir.Get()}

	// Non-Windows machines need to test for this special case of $HOME
	if runtime.GOOS != "windows" {
		homes = append(homes, "/")
	}

	homeKey := homedir.Key()
	baseEnvs := appendBaseEnv(true)

	// Remove HOME env var from list so we can add a new value later.
	for i, env := range baseEnvs {
		if strings.HasPrefix(env, homeKey+"=") {
			baseEnvs = append(baseEnvs[:i], baseEnvs[i+1:]...)
			break
		}
	}

	for _, home := range homes {
		// Dup baseEnvs and add our new HOME value
		newEnvs := make([]string, len(baseEnvs)+1)
		copy(newEnvs, baseEnvs)
		newEnvs[len(newEnvs)-1] = homeKey + "=" + home

		scanForHome := runtime.GOOS != "windows" && home != "/"

		// Check main help text to make sure its not over 80 chars
		helpCmd := exec.Command(dockerBinary, "help")
		helpCmd.Env = newEnvs
		out, _, err := runCommandWithOutput(helpCmd)
		c.Assert(err, checker.IsNil, check.Commentf(out))
		lines := strings.Split(out, "\n")
		foundTooLongLine := false
		for _, line := range lines {
			if !foundTooLongLine && len(line) > 80 {
				c.Logf("Line is too long:\n%s", line)
				foundTooLongLine = true
			}
			// All lines should not end with a space
			c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Line should not end with a space"))

			if scanForHome && strings.Contains(line, `=`+home) {
				c.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
			}
			if runtime.GOOS != "windows" {
				i := strings.Index(line, homedir.GetShortcutString())
				if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
					c.Fatalf("Main help should not have used home shortcut:\n%s", line)
				}
			}
		}

		// Make sure each cmd's help text fits within 90 chars and that
		// on non-windows system we use ~ when possible (to shorten things).
		// Pull the list of commands from the "Commands:" section of docker help
		helpCmd = exec.Command(dockerBinary, "help")
		helpCmd.Env = newEnvs
		out, _, err = runCommandWithOutput(helpCmd)
		c.Assert(err, checker.IsNil, check.Commentf(out))
		i := strings.Index(out, "Commands:")
		c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", out))

		cmds := []string{}
		// Grab all chars starting at "Commands:"
		helpOut := strings.Split(out[i:], "\n")
		// First line is just "Commands:"
		if isLocalDaemon {
			// Replace first line with "daemon" command since it's not part of the list of commands.
			helpOut[0] = " daemon"
		} else {
			// Skip first line
			helpOut = helpOut[1:]
		}

		// Create the list of commands we want to test
		cmdsToTest := []string{}
		for _, cmd := range helpOut {
			// Stop on blank line or non-idented line
			if cmd == "" || !unicode.IsSpace(rune(cmd[0])) {
				break
			}

			// Grab just the first word of each line
			cmd = strings.Split(strings.TrimSpace(cmd), " ")[0]
			cmds = append(cmds, cmd) // Saving count for later

			cmdsToTest = append(cmdsToTest, cmd)
		}

		// Add some 'two word' commands - would be nice to automatically
		// calculate this list - somehow
		cmdsToTest = append(cmdsToTest, "volume create")
		cmdsToTest = append(cmdsToTest, "volume inspect")
		cmdsToTest = append(cmdsToTest, "volume ls")
		cmdsToTest = append(cmdsToTest, "volume rm")

		for _, cmd := range cmdsToTest {
			var stderr string

			args := strings.Split(cmd+" --help", " ")

			// Check the full usage text
			helpCmd := exec.Command(dockerBinary, args...)
			helpCmd.Env = newEnvs
			out, stderr, _, err = runCommandWithStdoutStderr(helpCmd)
			c.Assert(len(stderr), checker.Equals, 0, check.Commentf("Error on %q help. non-empty stderr:%q", cmd, stderr))
			c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have blank line on %q\n", cmd))
			c.Assert(out, checker.Contains, "--help", check.Commentf("All commands should mention '--help'. Command '%v' did not.\n", cmd))

			c.Assert(err, checker.IsNil, check.Commentf(out))

			// Check each line for lots of stuff
			lines := strings.Split(out, "\n")
			for _, line := range lines {
				c.Assert(len(line), checker.LessOrEqualThan, 107, check.Commentf("Help for %q is too long:\n%s", cmd, line))

				if scanForHome && strings.Contains(line, `"`+home) {
					c.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
						cmd, home, line)
				}
				i := strings.Index(line, "~")
				if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
					c.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
				}

				// If a line starts with 4 spaces then assume someone
				// added a multi-line description for an option and we need
				// to flag it
				c.Assert(line, checker.Not(checker.HasPrefix), "    ", check.Commentf("Help for %q should not have a multi-line option", cmd))

				// Options should NOT end with a period
				if strings.HasPrefix(line, "  -") && strings.HasSuffix(line, ".") {
					c.Fatalf("Help for %q should not end with a period: %s", cmd, line)
				}

				// Options should NOT end with a space
				c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Help for %q should not end with a space", cmd))

			}

			// For each command make sure we generate an error
			// if we give a bad arg
			args = strings.Split(cmd+" --badArg", " ")

			out, _, err = dockerCmdWithError(args...)
			c.Assert(err, checker.NotNil, check.Commentf(out))
			// Be really picky
			c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker rm'\n"))

			// Now make sure that each command will print a short-usage
			// (not a full usage - meaning no opts section) if we
			// are missing a required arg or pass in a bad arg

			// These commands will never print a short-usage so don't test
			noShortUsage := map[string]string{
				"images":  "",
				"login":   "",
				"logout":  "",
				"network": "",
				"stats":   "",
			}

			if _, ok := noShortUsage[cmd]; !ok {
				// For each command run it w/o any args. It will either return
				// valid output or print a short-usage
				var dCmd *exec.Cmd
				var stdout, stderr string
				var args []string

				// skipNoArgs are ones that we don't want to try w/o
				// any args. Either because it'll hang the test or
				// lead to incorrect test result (like false negative).
				// Whatever the reason, skip trying to run w/o args and
				// jump to trying with a bogus arg.
				skipNoArgs := map[string]struct{}{
					"daemon": {},
					"events": {},
					"load":   {},
				}

				ec := 0
				if _, ok := skipNoArgs[cmd]; !ok {
					args = strings.Split(cmd, " ")
					dCmd = exec.Command(dockerBinary, args...)
					stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
				}

				// If its ok w/o any args then try again with an arg
				if ec == 0 {
					args = strings.Split(cmd+" badArg", " ")
					dCmd = exec.Command(dockerBinary, args...)
					stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
				}

				if len(stdout) != 0 || len(stderr) == 0 || ec == 0 || err == nil {
					c.Fatalf("Bad output from %q\nstdout:%q\nstderr:%q\nec:%d\nerr:%q", args, stdout, stderr, ec, err)
				}
				// Should have just short usage
				c.Assert(stderr, checker.Contains, "\nUsage:\t", check.Commentf("Missing short usage on %q\n", args))
				// But shouldn't have full usage
				c.Assert(stderr, checker.Not(checker.Contains), "--help=false", check.Commentf("Should not have full usage on %q\n", args))
				c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line on %q\n", args))
			}

		}

		// Number of commands for standard release and experimental release
		standard := 41
		experimental := 1
		expected := standard + experimental
		if isLocalDaemon {
			expected++ // for the daemon command
		}
		c.Assert(len(cmds), checker.LessOrEqualThan, expected, check.Commentf("Wrong # of cmds, it should be: %d\nThe list:\n%q", expected, cmds))
	}

}
Esempio n. 19
0
func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *check.C) {
	// setup image1
	digest1, err := setupImageWithTag(c, "dangle1")
	c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
	imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
	c.Logf("imageReference1 = %s", imageReference1)

	// pull image1 by digest
	dockerCmd(c, "pull", imageReference1)

	// list images
	out, _ := dockerCmd(c, "images", "--digests")

	// make sure repo shown, tag=<none>, digest = $digest1
	re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`)
	c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out))
	// setup image2
	digest2, err := setupImageWithTag(c, "dangle2")
	//error setting up image
	c.Assert(err, checker.IsNil)
	imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
	c.Logf("imageReference2 = %s", imageReference2)

	// pull image1 by digest
	dockerCmd(c, "pull", imageReference1)

	// pull image2 by digest
	dockerCmd(c, "pull", imageReference2)

	// list images
	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")

	// make sure repo shown, tag=<none>, digest = $digest1
	c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out))

	// make sure repo shown, tag=<none>, digest = $digest2
	re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2.String() + `\s`)
	c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out))

	// pull dangle1 tag
	dockerCmd(c, "pull", repoName+":dangle1")

	// list images
	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")

	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*dangle1\s*` + digest1.String() + `\s`)
	c.Assert(reWithDigest1.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest1.String(), out))
	// make sure image 2 has repo, <none>, digest
	c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out))

	// pull dangle2 tag
	dockerCmd(c, "pull", repoName+":dangle2")

	// list images, show tagged images
	out, _ = dockerCmd(c, "images", "--digests")

	// make sure image 1 has repo, tag, digest
	c.Assert(reWithDigest1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest1.String(), out))

	// make sure image 2 has repo, tag, digest
	reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*dangle2\s*` + digest2.String() + `\s`)
	c.Assert(reWithDigest2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest2.String(), out))

	// list images, no longer dangling, should not match
	out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"")

	// make sure image 1 has repo, tag, digest
	c.Assert(reWithDigest1.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest1.String(), out))
	// make sure image 2 has repo, tag, digest
	c.Assert(reWithDigest2.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest2.String(), out))
}
Esempio n. 20
0
func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
	testRequires(c, DaemonIsLinux)

	// Make sure main help text fits within 80 chars and that
	// on non-windows system we use ~ when possible (to shorten things).
	// Test for HOME set to its default value and set to "/" on linux
	// Yes on windows setting up an array and looping (right now) isn't
	// necessary because we just have one value, but we'll need the
	// array/loop on linux so we might as well set it up so that we can
	// test any number of home dirs later on and all we need to do is
	// modify the array - the rest of the testing infrastructure should work
	homes := []string{homedir.Get()}

	// Non-Windows machines need to test for this special case of $HOME
	if runtime.GOOS != "windows" {
		homes = append(homes, "/")
	}

	homeKey := homedir.Key()
	baseEnvs := appendBaseEnv(true)

	// Remove HOME env var from list so we can add a new value later.
	for i, env := range baseEnvs {
		if strings.HasPrefix(env, homeKey+"=") {
			baseEnvs = append(baseEnvs[:i], baseEnvs[i+1:]...)
			break
		}
	}

	for _, home := range homes {

		// Dup baseEnvs and add our new HOME value
		newEnvs := make([]string, len(baseEnvs)+1)
		copy(newEnvs, baseEnvs)
		newEnvs[len(newEnvs)-1] = homeKey + "=" + home

		scanForHome := runtime.GOOS != "windows" && home != "/"

		// Check main help text to make sure its not over 80 chars
		helpCmd := exec.Command(dockerBinary, "help")
		helpCmd.Env = newEnvs
		out, _, err := runCommandWithOutput(helpCmd)
		c.Assert(err, checker.IsNil, check.Commentf(out))
		lines := strings.Split(out, "\n")
		foundTooLongLine := false
		for _, line := range lines {
			if !foundTooLongLine && len(line) > 80 {
				c.Logf("Line is too long:\n%s", line)
				foundTooLongLine = true
			}
			// All lines should not end with a space
			c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Line should not end with a space"))

			if scanForHome && strings.Contains(line, `=`+home) {
				c.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
			}
			if runtime.GOOS != "windows" {
				i := strings.Index(line, homedir.GetShortcutString())
				if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
					c.Fatalf("Main help should not have used home shortcut:\n%s", line)
				}
			}
		}

		// Make sure each cmd's help text fits within 90 chars and that
		// on non-windows system we use ~ when possible (to shorten things).
		// Pull the list of commands from the "Commands:" section of docker help
		helpCmd = exec.Command(dockerBinary, "help")
		helpCmd.Env = newEnvs
		out, _, err = runCommandWithOutput(helpCmd)
		c.Assert(err, checker.IsNil, check.Commentf(out))
		i := strings.Index(out, "Commands:")
		c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", out))

		cmds := []string{}
		// Grab all chars starting at "Commands:"
		helpOut := strings.Split(out[i:], "\n")
		// First line is just "Commands:"
		if isLocalDaemon {
			// Replace first line with "daemon" command since it's not part of the list of commands.
			helpOut[0] = " daemon"
		} else {
			// Skip first line
			helpOut = helpOut[1:]
		}

		// Create the list of commands we want to test
		cmdsToTest := []string{}
		for _, cmd := range helpOut {
			// Stop on blank line or non-idented line
			if cmd == "" || !unicode.IsSpace(rune(cmd[0])) {
				break
			}

			// Grab just the first word of each line
			cmd = strings.Split(strings.TrimSpace(cmd), " ")[0]
			cmds = append(cmds, cmd) // Saving count for later

			cmdsToTest = append(cmdsToTest, cmd)
		}

		// Add some 'two word' commands - would be nice to automatically
		// calculate this list - somehow
		cmdsToTest = append(cmdsToTest, "volume create")
		cmdsToTest = append(cmdsToTest, "volume inspect")
		cmdsToTest = append(cmdsToTest, "volume ls")
		cmdsToTest = append(cmdsToTest, "volume rm")

		// Divide the list of commands into go routines and  run the func testcommand on the commands in parallel
		// to save runtime of test

		errChan := make(chan error)

		for index := 0; index < len(cmdsToTest); index++ {
			go func(index int) {
				errChan <- testCommand(cmdsToTest[index], newEnvs, scanForHome, home)
			}(index)
		}

		for index := 0; index < len(cmdsToTest); index++ {
			err := <-errChan
			if err != nil {
				c.Fatal(err)
			}
		}

		// Number of commands for standard release and experimental release
		standard := 41
		experimental := 1
		expected := standard + experimental
		if isLocalDaemon {
			expected++ // for the daemon command
		}
		c.Assert(len(cmds), checker.LessOrEqualThan, expected, check.Commentf("Wrong # of cmds, it should be: %d\nThe list:\n%q", expected, cmds))
	}

}
Esempio n. 21
0
func (s *DockerRegistrySuite) TestListImagesWithDigests(c *check.C) {

	// setup image1
	digest1, err := setupImageWithTag(c, "tag1")
	c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
	imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
	c.Logf("imageReference1 = %s", imageReference1)

	// pull image1 by digest
	dockerCmd(c, "pull", imageReference1)

	// list images
	out, _ := dockerCmd(c, "images", "--digests")

	// make sure repo shown, tag=<none>, digest = $digest1
	re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`)
	c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out))
	// setup image2
	digest2, err := setupImageWithTag(c, "tag2")
	//error setting up image
	c.Assert(err, checker.IsNil)
	imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
	c.Logf("imageReference2 = %s", imageReference2)

	// pull image1 by digest
	dockerCmd(c, "pull", imageReference1)

	// pull image2 by digest
	dockerCmd(c, "pull", imageReference2)

	// list images
	out, _ = dockerCmd(c, "images", "--digests")

	// make sure repo shown, tag=<none>, digest = $digest1
	c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out))

	// make sure repo shown, tag=<none>, digest = $digest2
	re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2.String() + `\s`)
	c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out))

	// pull tag1
	dockerCmd(c, "pull", repoName+":tag1")

	// list images
	out, _ = dockerCmd(c, "images", "--digests")

	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
	reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`)
	c.Assert(reWithDigest1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest1.String(), out))
	c.Assert(reWithTag1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithTag1.String(), out))
	// make sure image 2 has repo, <none>, digest
	c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out))

	// pull tag 2
	dockerCmd(c, "pull", repoName+":tag2")

	// list images
	out, _ = dockerCmd(c, "images", "--digests")

	// make sure image 1 has repo, tag, digest
	c.Assert(reWithTag1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithTag1.String(), out))

	// make sure image 2 has repo, tag, digest
	reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
	reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2.String() + `\s`)
	c.Assert(reWithTag2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithTag2.String(), out))
	c.Assert(reWithDigest2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest2.String(), out))

	// list images
	out, _ = dockerCmd(c, "images", "--digests")

	// make sure image 1 has repo, tag, digest
	c.Assert(reWithTag1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithTag1.String(), out))
	// make sure image 2 has repo, tag, digest
	c.Assert(reWithTag2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithTag2.String(), out))
	// make sure busybox has tag, but not digest
	busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
	c.Assert(busyboxRe.MatchString(out), checker.True, check.Commentf("expected %q: %s", busyboxRe.String(), out))
}
func (s *DockerRegistrySuite) TestListImagesWithDigests(c *check.C) {

	// setup image1
	digest1, err := setupImageWithTag("tag1")
	if err != nil {
		c.Fatalf("error setting up image: %v", err)
	}
	imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
	c.Logf("imageReference1 = %s", imageReference1)

	// pull image1 by digest
	cmd := exec.Command(dockerBinary, "pull", imageReference1)
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error pulling by digest: %s, %v", out, err)
	}

	// list images
	cmd = exec.Command(dockerBinary, "images", "--digests")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error listing images: %s, %v", out, err)
	}

	// make sure repo shown, tag=<none>, digest = $digest1
	re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
	if !re1.MatchString(out) {
		c.Fatalf("expected %q: %s", re1.String(), out)
	}

	// setup image2
	digest2, err := setupImageWithTag("tag2")
	if err != nil {
		c.Fatalf("error setting up image: %v", err)
	}
	imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
	c.Logf("imageReference2 = %s", imageReference2)

	// pull image1 by digest
	cmd = exec.Command(dockerBinary, "pull", imageReference1)
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error pulling by digest: %s, %v", out, err)
	}

	// pull image2 by digest
	cmd = exec.Command(dockerBinary, "pull", imageReference2)
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error pulling by digest: %s, %v", out, err)
	}

	// list images
	cmd = exec.Command(dockerBinary, "images", "--digests")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error listing images: %s, %v", out, err)
	}

	// make sure repo shown, tag=<none>, digest = $digest1
	if !re1.MatchString(out) {
		c.Fatalf("expected %q: %s", re1.String(), out)
	}

	// make sure repo shown, tag=<none>, digest = $digest2
	re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
	if !re2.MatchString(out) {
		c.Fatalf("expected %q: %s", re2.String(), out)
	}

	// pull tag1
	cmd = exec.Command(dockerBinary, "pull", repoName+":tag1")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error pulling tag1: %s, %v", out, err)
	}

	// list images
	cmd = exec.Command(dockerBinary, "images", "--digests")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error listing images: %s, %v", out, err)
	}

	// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
	reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
	reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
	if !reWithTag1.MatchString(out) {
		c.Fatalf("expected %q: %s", reWithTag1.String(), out)
	}
	if !reWithDigest1.MatchString(out) {
		c.Fatalf("expected %q: %s", reWithDigest1.String(), out)
	}
	// make sure image 2 has repo, <none>, digest
	if !re2.MatchString(out) {
		c.Fatalf("expected %q: %s", re2.String(), out)
	}

	// pull tag 2
	cmd = exec.Command(dockerBinary, "pull", repoName+":tag2")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error pulling tag2: %s, %v", out, err)
	}

	// list images
	cmd = exec.Command(dockerBinary, "images", "--digests")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error listing images: %s, %v", out, err)
	}

	// make sure image 1 has repo, tag, digest
	if !reWithTag1.MatchString(out) {
		c.Fatalf("expected %q: %s", re1.String(), out)
	}

	// make sure image 2 has repo, tag, digest
	reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
	reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
	if !reWithTag2.MatchString(out) {
		c.Fatalf("expected %q: %s", reWithTag2.String(), out)
	}
	if !reWithDigest2.MatchString(out) {
		c.Fatalf("expected %q: %s", reWithDigest2.String(), out)
	}

	// list images
	cmd = exec.Command(dockerBinary, "images", "--digests")
	out, _, err = runCommandWithOutput(cmd)
	if err != nil {
		c.Fatalf("error listing images: %s, %v", out, err)
	}

	// make sure image 1 has repo, tag, digest
	if !reWithTag1.MatchString(out) {
		c.Fatalf("expected %q: %s", re1.String(), out)
	}
	// make sure image 2 has repo, tag, digest
	if !reWithTag2.MatchString(out) {
		c.Fatalf("expected %q: %s", re2.String(), out)
	}
	// make sure busybox has tag, but not digest
	busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
	if !busyboxRe.MatchString(out) {
		c.Fatalf("expected %q: %s", busyboxRe.String(), out)
	}
}