Merge branch 'master' of github.com:docker/docker into kill

Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
This commit is contained in:
Dan Walsh
2015-05-27 11:00:12 -04:00
753 changed files with 38823 additions and 18972 deletions
+509 -71
View File
@@ -1,17 +1,20 @@
package main
import (
"archive/tar"
"bytes"
"encoding/json"
"io"
"net/http"
"net/http/httputil"
"os"
"os/exec"
"strings"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/docker/docker/runconfig"
"github.com/go-check/check"
)
@@ -163,7 +166,7 @@ func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) {
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(err, check.IsNil)
if !strings.Contains(string(body), "Duplicate volume") {
if !strings.Contains(string(body), "Duplicate bind") {
c.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
}
}
@@ -207,49 +210,6 @@ func (s *DockerSuite) TestContainerApiStartVolumesFrom(c *check.C) {
}
}
// Ensure that volumes-from has priority over binds/anything else
// This is pretty much the same as TestRunApplyVolumesFromBeforeVolumes, except with passing the VolumesFrom and the bind on start
func (s *DockerSuite) TestVolumesFromHasPriority(c *check.C) {
volName := "voltst2"
volPath := "/tmp"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
c.Fatal(out, err)
}
name := "testing"
config := map[string]interface{}{
"Image": "busybox",
"Volumes": map[string]struct{}{volPath: {}},
}
status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(status, check.Equals, http.StatusCreated)
c.Assert(err, check.IsNil)
bindPath := randomUnixTmpDirPath("test")
config = map[string]interface{}{
"VolumesFrom": []string{volName},
"Binds": []string{bindPath + ":/tmp"},
}
status, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
pth, err := inspectFieldMap(name, "Volumes", volPath)
if err != nil {
c.Fatal(err)
}
pth2, err := inspectFieldMap(volName, "Volumes", volPath)
if err != nil {
c.Fatal(err)
}
if pth != pth2 {
c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
}
}
func (s *DockerSuite) TestGetContainerStats(c *check.C) {
var (
name = "statscontainer"
@@ -674,46 +634,133 @@ func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
}
func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
var hostName = "test-host"
hostName := "test-host"
config := map[string]interface{}{
"Image": "busybox",
"Hostname": hostName,
}
_, b, err := sockRequest("POST", "/containers/create", config)
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
c.Fatal(err)
}
type createResp struct {
Id string
}
var container createResp
if err := json.Unmarshal(b, &container); err != nil {
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
if err := json.Unmarshal(body, &container); err != nil {
c.Fatal(err)
}
var id = container.Id
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
_, bodyGet, err := sockRequest("GET", "/containers/"+id+"/json", nil)
type configLocal struct {
Hostname string
}
type getResponse struct {
Id string
Config configLocal
}
var containerInfo getResponse
if err := json.Unmarshal(bodyGet, &containerInfo); err != nil {
var containerJSON types.ContainerJSON
if err := json.Unmarshal(body, &containerJSON); err != nil {
c.Fatal(err)
}
var hostNameActual = containerInfo.Config.Hostname
if hostNameActual != "test-host" {
c.Fatalf("Mismatched Hostname, Expected %v, Actual: %v ", hostName, hostNameActual)
if containerJSON.Config.Hostname != hostName {
c.Fatalf("Mismatched Hostname, Expected %s, Actual: %s ", hostName, containerJSON.Config.Hostname)
}
}
func (s *DockerSuite) TestContainerApiCreateWithDomainName(c *check.C) {
domainName := "test-domain"
config := map[string]interface{}{
"Image": "busybox",
"Domainname": domainName,
}
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
if err := json.Unmarshal(body, &container); err != nil {
c.Fatal(err)
}
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
var containerJSON types.ContainerJSON
if err := json.Unmarshal(body, &containerJSON); err != nil {
c.Fatal(err)
}
if containerJSON.Config.Domainname != domainName {
c.Fatalf("Mismatched Domainname, Expected %s, Actual: %s ", domainName, containerJSON.Config.Domainname)
}
}
func (s *DockerSuite) TestContainerApiCreateNetworkMode(c *check.C) {
UtilCreateNetworkMode(c, "host")
UtilCreateNetworkMode(c, "bridge")
UtilCreateNetworkMode(c, "container:web1")
}
func UtilCreateNetworkMode(c *check.C, networkMode string) {
config := map[string]interface{}{
"Image": "busybox",
"HostConfig": map[string]interface{}{"NetworkMode": networkMode},
}
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
if err := json.Unmarshal(body, &container); err != nil {
c.Fatal(err)
}
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
var containerJSON types.ContainerJSON
if err := json.Unmarshal(body, &containerJSON); err != nil {
c.Fatal(err)
}
if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) {
c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode)
}
}
func (s *DockerSuite) TestContainerApiCreateWithCpuSharesCpuset(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
"CpuShares": 512,
"CpusetCpus": "0,1",
}
status, body, err := sockRequest("POST", "/containers/create", config)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated)
var container types.ContainerCreateResponse
if err := json.Unmarshal(body, &container); err != nil {
c.Fatal(err)
}
status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
var containerJson types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJson), check.IsNil)
out, err := inspectField(containerJson.Id, "HostConfig.CpuShares")
c.Assert(err, check.IsNil)
c.Assert(out, check.Equals, "512")
outCpuset, errCpuset := inspectField(containerJson.Id, "HostConfig.CpusetCpus")
c.Assert(errCpuset, check.IsNil, check.Commentf("Output: %s", outCpuset))
c.Assert(outCpuset, check.Equals, "0,1")
}
func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
@@ -796,6 +843,17 @@ func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
if out != "" {
c.Fatalf("expected empty string, got %q", out)
}
outMemory, errMemory := inspectField(container.Id, "HostConfig.Memory")
c.Assert(outMemory, check.Equals, "0")
if errMemory != nil {
c.Fatal(errMemory, outMemory)
}
outMemorySwap, errMemorySwap := inspectField(container.Id, "HostConfig.MemorySwap")
c.Assert(outMemorySwap, check.Equals, "0")
if errMemorySwap != nil {
c.Fatal(errMemorySwap, outMemorySwap)
}
}
func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
@@ -858,3 +916,383 @@ func (s *DockerSuite) TestContainerApiRename(c *check.C) {
c.Fatalf("Failed to rename container, expected %v, got %v. Container rename API failed", newName, name)
}
}
func (s *DockerSuite) TestContainerApiKill(c *check.C) {
name := "test-api-kill"
runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
status, _, err := sockRequest("POST", "/containers/"+name+"/kill", nil)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
state, err := inspectField(name, "State.Running")
if err != nil {
c.Fatal(err)
}
if state != "false" {
c.Fatalf("got wrong State from container %s: %q", name, state)
}
}
func (s *DockerSuite) TestContainerApiRestart(c *check.C) {
name := "test-api-restart"
runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
status, _, err := sockRequest("POST", "/containers/"+name+"/restart?t=1", nil)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
if err := waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 5); err != nil {
c.Fatal(err)
}
}
func (s *DockerSuite) TestContainerApiRestartNotimeoutParam(c *check.C) {
name := "test-api-restart-no-timeout-param"
runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
status, _, err := sockRequest("POST", "/containers/"+name+"/restart", nil)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
if err := waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 5); err != nil {
c.Fatal(err)
}
}
func (s *DockerSuite) TestContainerApiStart(c *check.C) {
name := "testing-start"
config := map[string]interface{}{
"Image": "busybox",
"Cmd": []string{"/bin/sh", "-c", "/bin/top"},
"OpenStdin": true,
}
status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
c.Assert(status, check.Equals, http.StatusCreated)
c.Assert(err, check.IsNil)
conf := make(map[string]interface{})
status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
// second call to start should give 304
status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
c.Assert(status, check.Equals, http.StatusNotModified)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestContainerApiStop(c *check.C) {
name := "test-api-stop"
runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
status, _, err := sockRequest("POST", "/containers/"+name+"/stop?t=1", nil)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
if err := waitInspect(name, "{{ .State.Running }}", "false", 5); err != nil {
c.Fatal(err)
}
// second call to start should give 304
status, _, err = sockRequest("POST", "/containers/"+name+"/stop?t=1", nil)
c.Assert(status, check.Equals, http.StatusNotModified)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestContainerApiWait(c *check.C) {
name := "test-api-wait"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sleep", "5")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
status, body, err := sockRequest("POST", "/containers/"+name+"/wait", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
if err := waitInspect(name, "{{ .State.Running }}", "false", 5); err != nil {
c.Fatal(err)
}
var waitres types.ContainerWaitResponse
if err := json.Unmarshal(body, &waitres); err != nil {
c.Fatalf("unable to unmarshal response body: %v", err)
}
if waitres.StatusCode != 0 {
c.Fatalf("Expected wait response StatusCode to be 0, got %d", waitres.StatusCode)
}
}
func (s *DockerSuite) TestContainerApiCopy(c *check.C) {
name := "test-container-api-copy"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt")
_, err := runCommand(runCmd)
c.Assert(err, check.IsNil)
postData := types.CopyConfig{
Resource: "/test.txt",
}
status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
found := false
for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
h, err := tarReader.Next()
if err != nil {
if err == io.EOF {
break
}
c.Fatal(err)
}
if h.Name == "test.txt" {
found = true
break
}
}
c.Assert(found, check.Equals, true)
}
func (s *DockerSuite) TestContainerApiCopyResourcePathEmpty(c *check.C) {
name := "test-container-api-copy-resource-empty"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt")
_, err := runCommand(runCmd)
c.Assert(err, check.IsNil)
postData := types.CopyConfig{
Resource: "",
}
status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(string(body), check.Matches, "Path cannot be empty\n")
}
func (s *DockerSuite) TestContainerApiCopyResourcePathNotFound(c *check.C) {
name := "test-container-api-copy-resource-not-found"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox")
_, err := runCommand(runCmd)
c.Assert(err, check.IsNil)
postData := types.CopyConfig{
Resource: "/notexist",
}
status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(string(body), check.Matches, "Could not find the file /notexist in container "+name+"\n")
}
func (s *DockerSuite) TestContainerApiCopyContainerNotFound(c *check.C) {
postData := types.CopyConfig{
Resource: "/something",
}
status, _, err := sockRequest("POST", "/containers/notexists/copy", postData)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNotFound)
}
func (s *DockerSuite) TestContainerApiDelete(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
stopCmd := exec.Command(dockerBinary, "stop", id)
_, err = runCommand(stopCmd)
c.Assert(err, check.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id, nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNoContent)
}
func (s *DockerSuite) TestContainerApiDeleteNotExist(c *check.C) {
status, body, err := sockRequest("DELETE", "/containers/doesnotexist", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNotFound)
c.Assert(string(body), check.Matches, "no such id: doesnotexist\n")
}
func (s *DockerSuite) TestContainerApiDeleteForce(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id+"?force=1", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNoContent)
}
func (s *DockerSuite) TestContainerApiDeleteRemoveLinks(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "tlink1", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
runCmd = exec.Command(dockerBinary, "run", "--link", "tlink1:tlink1", "--name", "tlink2", "-d", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id2 := strings.TrimSpace(out)
c.Assert(waitRun(id2), check.IsNil)
links, err := inspectFieldJSON(id2, "HostConfig.Links")
c.Assert(err, check.IsNil)
if links != "[\"/tlink1:/tlink2/tlink1\"]" {
c.Fatal("expected to have links between containers")
}
status, _, err := sockRequest("DELETE", "/containers/tlink2/tlink1?link=1", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusNoContent)
linksPostRm, err := inspectFieldJSON(id2, "HostConfig.Links")
c.Assert(err, check.IsNil)
if linksPostRm != "null" {
c.Fatal("call to api deleteContainer links should have removed the specified links")
}
}
func (s *DockerSuite) TestContainerApiDeleteConflict(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id, nil)
c.Assert(status, check.Equals, http.StatusConflict)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestContainerApiDeleteRemoveVolume(c *check.C) {
testRequires(c, SameHostDaemon)
runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/testvolume", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
vol, err := inspectFieldMap(id, "Volumes", "/testvolume")
c.Assert(err, check.IsNil)
_, err = os.Stat(vol)
c.Assert(err, check.IsNil)
status, _, err := sockRequest("DELETE", "/containers/"+id+"?v=1&force=1", nil)
c.Assert(status, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
if _, err := os.Stat(vol); !os.IsNotExist(err) {
c.Fatalf("expected to get ErrNotExist error, got %v", err)
}
}
// Regression test for https://github.com/docker/docker/issues/6231
func (s *DockerSuite) TestContainersApiChunkedEncoding(c *check.C) {
out, _ := dockerCmd(c, "create", "-v", "/foo", "busybox", "true")
id := strings.TrimSpace(out)
conn, err := sockConn(time.Duration(10 * time.Second))
if err != nil {
c.Fatal(err)
}
client := httputil.NewClientConn(conn, nil)
defer client.Close()
bindCfg := strings.NewReader(`{"Binds": ["/tmp:/foo"]}`)
req, err := http.NewRequest("POST", "/containers/"+id+"/start", bindCfg)
if err != nil {
c.Fatal(err)
}
req.Header.Set("Content-Type", "application/json")
// This is a cheat to make the http request do chunked encoding
// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
// https://golang.org/src/pkg/net/http/request.go?s=11980:12172
req.ContentLength = -1
resp, err := client.Do(req)
if err != nil {
c.Fatalf("error starting container with chunked encoding: %v", err)
}
resp.Body.Close()
if resp.StatusCode != 204 {
c.Fatalf("expected status code 204, got %d", resp.StatusCode)
}
out, err = inspectFieldJSON(id, "HostConfig.Binds")
if err != nil {
c.Fatal(err)
}
var binds []string
if err := json.NewDecoder(strings.NewReader(out)).Decode(&binds); err != nil {
c.Fatal(err)
}
if len(binds) != 1 {
c.Fatalf("got unexpected binds: %v", binds)
}
expected := "/tmp:/foo"
if binds[0] != expected {
c.Fatalf("got incorrect bind spec, wanted %s, got: %s", expected, binds[0])
}
}
func (s *DockerSuite) TestPostContainerStop(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
containerID := strings.TrimSpace(out)
c.Assert(waitRun(containerID), check.IsNil)
statusCode, _, err := sockRequest("POST", "/containers/"+containerID+"/stop", nil)
// 204 No Content is expected, not 200
c.Assert(statusCode, check.Equals, http.StatusNoContent)
c.Assert(err, check.IsNil)
if err := waitInspect(containerID, "{{ .State.Running }}", "false", 5); err != nil {
c.Fatal(err)
}
}
+50 -16
View File
@@ -11,21 +11,6 @@ import (
"github.com/go-check/check"
)
func (s *DockerSuite) TestLegacyImages(c *check.C) {
status, body, err := sockRequest("GET", "/v1.6/images/json", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
images := []types.LegacyImage{}
if err = json.Unmarshal(body, &images); err != nil {
c.Fatalf("Error on unmarshal: %s", err)
}
if len(images) == 0 || images[0].Tag == "" || images[0].Repository == "" {
c.Fatalf("Bad data: %q", images)
}
}
func (s *DockerSuite) TestApiImagesFilter(c *check.C) {
name := "utest:tag1"
name2 := "utest/docker:tag2"
@@ -35,7 +20,7 @@ func (s *DockerSuite) TestApiImagesFilter(c *check.C) {
c.Fatal(err, out)
}
}
type image struct{ RepoTags []string }
type image types.Image
getImages := func(filter string) []image {
v := url.Values{}
v.Set("filter", filter)
@@ -98,3 +83,52 @@ func (s *DockerSuite) TestApiImagesSaveAndLoad(c *check.C) {
c.Fatal("load did not work properly")
}
}
func (s *DockerSuite) TestApiImagesDelete(c *check.C) {
testRequires(c, Network)
name := "test-api-images-delete"
out, err := buildImage(name, "FROM hello-world\nENV FOO bar", false)
if err != nil {
c.Fatal(err)
}
defer deleteImages(name)
id := strings.TrimSpace(out)
if out, err := exec.Command(dockerBinary, "tag", name, "test:tag1").CombinedOutput(); err != nil {
c.Fatal(err, out)
}
status, _, err := sockRequest("DELETE", "/images/"+id, nil)
c.Assert(status, check.Equals, http.StatusConflict)
c.Assert(err, check.IsNil)
status, _, err = sockRequest("DELETE", "/images/test:noexist", nil)
c.Assert(status, check.Equals, http.StatusNotFound) //Status Codes:404 no such image
c.Assert(err, check.IsNil)
status, _, err = sockRequest("DELETE", "/images/test:tag1", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestApiImagesHistory(c *check.C) {
testRequires(c, Network)
name := "test-api-images-history"
out, err := buildImage(name, "FROM hello-world\nENV FOO bar", false)
c.Assert(err, check.IsNil)
defer deleteImages(name)
id := strings.TrimSpace(out)
status, body, err := sockRequest("GET", "/images/"+id+"/history", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
var historydata []types.ImageHistory
if err = json.Unmarshal(body, &historydata); err != nil {
c.Fatalf("Error on unmarshal: %s", err)
}
c.Assert(len(historydata), check.Not(check.Equals), 0)
c.Assert(historydata[0].Tags[0], check.Equals, "test-api-images-history:latest")
}
+17 -30
View File
@@ -18,40 +18,27 @@ func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) {
cleanedContainerID := strings.TrimSpace(out)
// test on json marshal version
// and latest version
testVersions := []string{"v1.11", "latest"}
endpoint := "/containers/" + cleanedContainerID + "/json"
status, body, err := sockRequest("GET", endpoint, nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
for _, testVersion := range testVersions {
endpoint := "/containers/" + cleanedContainerID + "/json"
if testVersion != "latest" {
endpoint = "/" + testVersion + endpoint
}
status, body, err := sockRequest("GET", endpoint, nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
var inspectJSON map[string]interface{}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
c.Fatalf("unable to unmarshal body for latest version: %v", err)
}
var inspectJSON map[string]interface{}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
c.Fatalf("unable to unmarshal body for %s version: %v", testVersion, err)
}
keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW"}
keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW"}
keys = append(keys, "Id")
if testVersion == "v1.11" {
keys = append(keys, "ID")
} else {
keys = append(keys, "Id")
}
for _, key := range keys {
if _, ok := inspectJSON[key]; !ok {
c.Fatalf("%s does not exist in response for %s version", key, testVersion)
}
}
//Issue #6830: type not properly converted to JSON/back
if _, ok := inspectJSON["Path"].(bool); ok {
c.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
for _, key := range keys {
if _, ok := inspectJSON[key]; !ok {
c.Fatalf("%s does not exist in response for latest version", key)
}
}
//Issue #6830: type not properly converted to JSON/back
if _, ok := inspectJSON["Path"].(bool); ok {
c.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
}
}
+21
View File
@@ -60,3 +60,24 @@ func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
c.Fatalf("Expected %s, got %s", expected, string(body[:]))
}
}
// Regression test for #12704
func (s *DockerSuite) TestLogsApiFollowEmptyOutput(c *check.C) {
name := "logs_test"
t0 := time.Now()
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "sleep", "10")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
c.Fatal(out, err)
}
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
t1 := time.Now()
body.Close()
if err != nil {
c.Fatal(err)
}
elapsed := t1.Sub(t0).Seconds()
if elapsed > 5.0 {
c.Fatalf("HTTP response was not immediate (elapsed %.1fs)", elapsed)
}
}
+42
View File
@@ -0,0 +1,42 @@
package main
import (
"net/http"
"net/http/httputil"
"time"
"github.com/go-check/check"
)
func (s *DockerSuite) TestApiOptionsRoute(c *check.C) {
status, _, err := sockRequest("OPTIONS", "/", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
res, body, err := sockRequestRaw("GET", "/version", nil, "")
body.Close()
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
// TODO: @runcom incomplete tests, why old integration tests had this headers
// and here none of the headers below are in the response?
//c.Log(res.Header)
//c.Assert(res.Header.Get("Access-Control-Allow-Origin"), check.Equals, "*")
//c.Assert(res.Header.Get("Access-Control-Allow-Headers"), check.Equals, "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
}
func (s *DockerSuite) TestVersionStatusCode(c *check.C) {
conn, err := sockConn(time.Duration(10 * time.Second))
c.Assert(err, check.IsNil)
client := httputil.NewClientConn(conn, nil)
defer client.Close()
req, err := http.NewRequest("GET", "/v999.0/version", nil)
c.Assert(err, check.IsNil)
req.Header.Set("User-Agent", "Docker-Client/999.0")
res, err := client.Do(req)
c.Assert(res.StatusCode, check.Equals, http.StatusBadRequest)
}
+147 -14
View File
@@ -611,7 +611,7 @@ ONBUILD ENTRYPOINT ["echo"]`,
}
func (s *DockerSuite) TestBuildCacheADD(c *check.C) {
func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
name := "testbuildtwoimageswithadd"
server, err := fakeStorage(map[string]string{
"robots.txt": "hello",
@@ -1112,10 +1112,10 @@ func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
"dir/nested_dir/nest_nest_file": "2 times nested",
"dirt": "dirty",
})
defer ctx.Close()
if err != nil {
c.Fatal(err)
}
defer ctx.Close()
id1, err := buildImageFromContext(name, ctx, true)
if err != nil {
@@ -1154,6 +1154,31 @@ func (s *DockerSuite) TestBuildCopyWildcardNoFind(c *check.C) {
}
func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) {
name := "testcopywildcardinname"
defer deleteImages(name)
ctx, err := fakeContext(`FROM busybox
COPY *.txt /tmp/
RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ]
`, map[string]string{"*.txt": "hi there"})
if err != nil {
// Normally we would do c.Fatal(err) here but given that
// the odds of this failing are so rare, it must be because
// the OS we're running the client on doesn't support * in
// filenames (like windows). So, instead of failing the test
// just let it pass. Then we don't need to explicitly
// say which OSs this works on or not.
return
}
defer ctx.Close()
_, err = buildImageFromContext(name, ctx, true)
if err != nil {
c.Fatalf("should have built: %q", err)
}
}
func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
name := "testcopywildcardcache"
ctx, err := fakeContext(`FROM busybox
@@ -2649,7 +2674,7 @@ func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDLocalFileWithCache(c *check.C) {
func (s *DockerSuite) TestBuildAddLocalFileWithCache(c *check.C) {
name := "testbuildaddlocalfilewithcache"
name2 := "testbuildaddlocalfilewithcache2"
dockerfile := `
@@ -2677,7 +2702,7 @@ func (s *DockerSuite) TestBuildADDLocalFileWithCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDMultipleLocalFileWithCache(c *check.C) {
func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) {
name := "testbuildaddmultiplelocalfilewithcache"
name2 := "testbuildaddmultiplelocalfilewithcache2"
dockerfile := `
@@ -2705,7 +2730,7 @@ func (s *DockerSuite) TestBuildADDMultipleLocalFileWithCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDLocalFileWithoutCache(c *check.C) {
func (s *DockerSuite) TestBuildAddLocalFileWithoutCache(c *check.C) {
name := "testbuildaddlocalfilewithoutcache"
name2 := "testbuildaddlocalfilewithoutcache2"
dockerfile := `
@@ -2763,7 +2788,7 @@ func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDCurrentDirWithCache(c *check.C) {
func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) {
name := "testbuildaddcurrentdirwithcache"
name2 := name + "2"
name3 := name + "3"
@@ -2827,7 +2852,7 @@ func (s *DockerSuite) TestBuildADDCurrentDirWithCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDCurrentDirWithoutCache(c *check.C) {
func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) {
name := "testbuildaddcurrentdirwithoutcache"
name2 := "testbuildaddcurrentdirwithoutcache2"
dockerfile := `
@@ -2854,7 +2879,7 @@ func (s *DockerSuite) TestBuildADDCurrentDirWithoutCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDRemoteFileWithCache(c *check.C) {
func (s *DockerSuite) TestBuildAddRemoteFileWithCache(c *check.C) {
name := "testbuildaddremotefilewithcache"
server, err := fakeStorage(map[string]string{
"baz": "hello",
@@ -2885,7 +2910,7 @@ func (s *DockerSuite) TestBuildADDRemoteFileWithCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDRemoteFileWithoutCache(c *check.C) {
func (s *DockerSuite) TestBuildAddRemoteFileWithoutCache(c *check.C) {
name := "testbuildaddremotefilewithoutcache"
name2 := "testbuildaddremotefilewithoutcache2"
server, err := fakeStorage(map[string]string{
@@ -2917,7 +2942,7 @@ func (s *DockerSuite) TestBuildADDRemoteFileWithoutCache(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDRemoteFileMTime(c *check.C) {
func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) {
name := "testbuildaddremotefilemtime"
name2 := name + "2"
name3 := name + "3"
@@ -2988,7 +3013,7 @@ func (s *DockerSuite) TestBuildADDRemoteFileMTime(c *check.C) {
}
}
func (s *DockerSuite) TestBuildADDLocalAndRemoteFilesWithCache(c *check.C) {
func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithCache(c *check.C) {
name := "testbuildaddlocalandremotefilewithcache"
server, err := fakeStorage(map[string]string{
"baz": "hello",
@@ -3070,7 +3095,7 @@ func (s *DockerSuite) TestBuildNoContext(c *check.C) {
}
// TODO: TestCaching
func (s *DockerSuite) TestBuildADDLocalAndRemoteFilesWithoutCache(c *check.C) {
func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithoutCache(c *check.C) {
name := "testbuildaddlocalandremotefilewithoutcache"
name2 := "testbuildaddlocalandremotefilewithoutcache2"
server, err := fakeStorage(map[string]string{
@@ -3190,7 +3215,7 @@ func (s *DockerSuite) TestBuildForbiddenContextPath(c *check.C) {
}
func (s *DockerSuite) TestBuildADDFileNotFound(c *check.C) {
func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) {
name := "testbuildaddnotfound"
ctx, err := fakeContext(`FROM scratch
ADD foo /usr/local/bar`,
@@ -4118,6 +4143,35 @@ func (s *DockerSuite) TestBuildFromGIT(c *check.C) {
}
}
func (s *DockerSuite) TestBuildFromGITWithContext(c *check.C) {
name := "testbuildfromgit"
defer deleteImages(name)
git, err := fakeGIT("repo", map[string]string{
"docker/Dockerfile": `FROM busybox
ADD first /first
RUN [ -f /first ]
MAINTAINER docker`,
"docker/first": "test git data",
}, true)
if err != nil {
c.Fatal(err)
}
defer git.Close()
u := fmt.Sprintf("%s#master:docker", git.RepoURL)
_, err = buildImageFromPath(name, u, true)
if err != nil {
c.Fatal(err)
}
res, err := inspectField(name, "Author")
if err != nil {
c.Fatal(err)
}
if res != "docker" {
c.Fatalf("Maintainer should be docker, got %s", res)
}
}
func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
name := "testbuildcmdcleanuponentrypoint"
if _, err := buildImage(name,
@@ -4754,7 +4808,7 @@ func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
c.Fatalf("test5 was supposed to fail to find passwd")
}
if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", strings.Replace(nonDockerfileFile, `\`, `\\`, -1)); !strings.Contains(out, expected) {
if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) {
c.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
}
@@ -5293,3 +5347,82 @@ func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
}
}
func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
testRequires(c, NativeExecDriver)
testRequires(c, SameHostDaemon)
defer deleteImages()
cgroupParent := "test"
data, err := ioutil.ReadFile("/proc/self/cgroup")
if err != nil {
c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
}
selfCgroupPaths := parseCgroupPaths(string(data))
_, found := selfCgroupPaths["memory"]
if !found {
c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
}
cmd := exec.Command(dockerBinary, "build", "--cgroup-parent", cgroupParent, "-")
cmd.Stdin = strings.NewReader(`
FROM busybox
RUN cat /proc/self/cgroup
`)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
}
}
func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
// Check to make sure our build output prints the Dockerfile cmd
// property - there was a bug that caused it to be duplicated on the
// Step X line
name := "testbuildnodupoutput"
_, out, err := buildImageWithOut(name, `
FROM busybox
RUN env`, false)
if err != nil {
c.Fatalf("Build should have worked: %q", err)
}
exp := "\nStep 1 : RUN env\n"
if !strings.Contains(out, exp) {
c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
}
}
func (s *DockerSuite) TestBuildBadCmdFlag(c *check.C) {
name := "testbuildbadcmdflag"
_, out, err := buildImageWithOut(name, `
FROM busybox
MAINTAINER --boo joe@example.com`, false)
if err == nil {
c.Fatal("Build should have failed")
}
exp := "\nUnknown flag: boo\n"
if !strings.Contains(out, exp) {
c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
}
}
func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
// Test to make sure the bad command is quoted with just "s and
// not as a Go []string
name := "testbuildbadrunerrmsg"
_, out, err := buildImageWithOut(name, `
FROM busybox
RUN badEXE a1 \& a2 a3`, false) // tab between a2 and a3
if err == nil {
c.Fatal("Should have failed to build")
}
exp := `The command '/bin/sh -c badEXE a1 \& a2 a3' returned a non-zero code: 127`
if !strings.Contains(out, exp) {
c.Fatalf("RUN doesn't have the correct output:\nGot:%s\nExpected:%s", out, exp)
}
}
@@ -115,6 +115,16 @@ func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) {
}
}
func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) {
// pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", repoName)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err == nil || !strings.Contains(out, "pulling with digest reference failed from v2 registry") {
c.Fatalf("expected non-zero exit status and correct error message when pulling non-existing image: %s", out)
}
}
func (s *DockerRegistrySuite) TestCreateByDigest(c *check.C) {
pushDigest, err := setupImage()
if err != nil {
+3 -10
View File
@@ -85,16 +85,11 @@ func (s *DockerSuite) TestCommitPausedContainer(c *check.C) {
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Paused}}", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(cmd)
if err != nil {
c.Fatalf("failed to inspect container: %v, output: %q", err, out)
}
out, err = inspectField(cleanedContainerID, "State.Paused")
c.Assert(err, check.IsNil)
if !strings.Contains(out, "true") {
c.Fatalf("commit should not unpause a paused container")
}
}
func (s *DockerSuite) TestCommitNewFile(c *check.C) {
@@ -242,9 +237,7 @@ func (s *DockerSuite) TestCommitChange(c *check.C) {
for conf, value := range expected {
res, err := inspectField(imageId, conf)
if err != nil {
c.Errorf("failed to get value %s, error: %s", conf, err)
}
c.Assert(err, check.IsNil)
if res != value {
c.Errorf("%s('%s'), expected %s", conf, res, value)
}
-1
View File
@@ -435,7 +435,6 @@ func (s *DockerSuite) TestCpVolumePath(c *check.C) {
}
cleanedContainerID := strings.TrimSpace(out)
defer dockerCmd(c, "rm", "-fv", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
+51
View File
@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"reflect"
@@ -290,3 +291,53 @@ func (s *DockerSuite) TestCreateHostnameWithNumber(c *check.C) {
c.Fatalf("hostname not set, expected `web.0`, got: %s", out)
}
}
func (s *DockerSuite) TestCreateRM(c *check.C) {
// Test to make sure we can 'rm' a new container that is in
// "Created" state, and has ever been run. Test "rm -f" too.
// create a container
createCmd := exec.Command(dockerBinary, "create", "busybox")
out, _, err := runCommandWithOutput(createCmd)
if err != nil {
c.Fatalf("Failed to create container:%s\n%s", out, err)
}
cID := strings.TrimSpace(out)
rmCmd := exec.Command(dockerBinary, "rm", cID)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
c.Fatalf("Failed to rm container:%s\n%s", out, err)
}
// Now do it again so we can "rm -f" this time
createCmd = exec.Command(dockerBinary, "create", "busybox")
out, _, err = runCommandWithOutput(createCmd)
if err != nil {
c.Fatalf("Failed to create 2nd container:%s\n%s", out, err)
}
cID = strings.TrimSpace(out)
rmCmd = exec.Command(dockerBinary, "rm", "-f", cID)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
c.Fatalf("Failed to rm -f container:%s\n%s", out, err)
}
}
func (s *DockerSuite) TestCreateModeIpcContainer(c *check.C) {
testRequires(c, SameHostDaemon)
cmd := exec.Command(dockerBinary, "create", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
id := strings.TrimSpace(out)
cmd = exec.Command(dockerBinary, "create", fmt.Sprintf("--ipc=container:%s", id), "busybox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatalf("Create container with ipc mode container should success with non running container: %s\n%s", out, err)
}
}
+381 -105
View File
@@ -6,12 +6,16 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/docker/libnetwork/iptables"
"github.com/docker/libtrust"
"github.com/go-check/check"
)
@@ -230,7 +234,7 @@ func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) {
}
content, _ := ioutil.ReadFile(s.d.logFile.Name())
if !strings.Contains(string(content), `level=debug`) {
c.Fatalf(`Missing level="debug" in log file using -D:\n%s`, string(content))
c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content))
}
}
@@ -240,7 +244,7 @@ func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) {
}
content, _ := ioutil.ReadFile(s.d.logFile.Name())
if !strings.Contains(string(content), `level=debug`) {
c.Fatalf(`Missing level="debug" in log file using --debug:\n%s`, string(content))
c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content))
}
}
@@ -250,7 +254,7 @@ func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) {
}
content, _ := ioutil.ReadFile(s.d.logFile.Name())
if !strings.Contains(string(content), `level=debug`) {
c.Fatalf(`Missing level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
}
}
@@ -280,35 +284,6 @@ func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) {
}
}
// #9629
func (s *DockerDaemonSuite) TestDaemonVolumesBindsRefs(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
tmp, err := ioutil.TempDir(os.TempDir(), "")
if err != nil {
c.Fatal(err)
}
defer os.RemoveAll(tmp)
if err := ioutil.WriteFile(tmp+"/test", []byte("testing"), 0655); err != nil {
c.Fatal(err)
}
if out, err := s.d.Cmd("create", "-v", tmp+":/foo", "--name=voltest", "busybox"); err != nil {
c.Fatal(err, out)
}
if err := s.d.Restart(); err != nil {
c.Fatal(err)
}
if out, err := s.d.Cmd("run", "--volumes-from=voltest", "--name=consumer", "busybox", "/bin/sh", "-c", "[ -f /foo/test ]"); err != nil {
c.Fatal(err, out)
}
}
func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) {
// TODO: skip or update for Windows daemon
os.Remove("/etc/docker/key.json")
@@ -356,76 +331,6 @@ func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) {
}
}
// Simulate an older daemon (pre 1.3) coming up with volumes specified in containers
// without corresponding volume json
func (s *DockerDaemonSuite) TestDaemonUpgradeWithVolumes(c *check.C) {
graphDir := filepath.Join(os.TempDir(), "docker-test")
defer os.RemoveAll(graphDir)
if err := s.d.StartWithBusybox("-g", graphDir); err != nil {
c.Fatal(err)
}
tmpDir := filepath.Join(os.TempDir(), "test")
defer os.RemoveAll(tmpDir)
if out, err := s.d.Cmd("create", "-v", tmpDir+":/foo", "--name=test", "busybox"); err != nil {
c.Fatal(err, out)
}
if err := s.d.Stop(); err != nil {
c.Fatal(err)
}
// Remove this since we're expecting the daemon to re-create it too
if err := os.RemoveAll(tmpDir); err != nil {
c.Fatal(err)
}
configDir := filepath.Join(graphDir, "volumes")
if err := os.RemoveAll(configDir); err != nil {
c.Fatal(err)
}
if err := s.d.Start("-g", graphDir); err != nil {
c.Fatal(err)
}
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
c.Fatalf("expected volume path %s to exist but it does not", tmpDir)
}
dir, err := ioutil.ReadDir(configDir)
if err != nil {
c.Fatal(err)
}
if len(dir) == 0 {
c.Fatalf("expected volumes config dir to contain data for new volume")
}
// Now with just removing the volume config and not the volume data
if err := s.d.Stop(); err != nil {
c.Fatal(err)
}
if err := os.RemoveAll(configDir); err != nil {
c.Fatal(err)
}
if err := s.d.Start("-g", graphDir); err != nil {
c.Fatal(err)
}
dir, err = ioutil.ReadDir(configDir)
if err != nil {
c.Fatal(err)
}
if len(dir) == 0 {
c.Fatalf("expected volumes config dir to contain data for new volume")
}
}
// GH#11320 - verify that the daemon exits on failure properly
// Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means
// to get a daemon init failure; no other tests for -b/--bip conflict are therefore required
@@ -447,6 +352,320 @@ func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) {
}
}
func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) {
d := s.d
err := d.Start("--bridge", "nosuchbridge")
c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail"))
defer d.Restart()
bridgeName := "external-bridge"
bridgeIp := "192.169.1.1/24"
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIp)
out, err := createInterface(c, "bridge", bridgeName, bridgeIp)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, bridgeName)
err = d.StartWithBusybox("--bridge", bridgeName)
c.Assert(err, check.IsNil)
ipTablesSearchString := bridgeIPNet.String()
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
out, _, err = runCommandWithOutput(ipTablesCmd)
c.Assert(err, check.IsNil)
c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true,
check.Commentf("iptables output should have contained %q, but was %q",
ipTablesSearchString, out))
_, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top")
c.Assert(err, check.IsNil)
containerIp := d.findContainerIP("ExtContainer")
ip := net.ParseIP(containerIp)
c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
check.Commentf("Container IP-Address must be in the same subnet range : %s",
containerIp))
}
func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) {
args := []string{"link", "add", "name", ifName, "type", ifType}
ipLinkCmd := exec.Command("ip", args...)
out, _, err := runCommandWithOutput(ipLinkCmd)
if err != nil {
return out, err
}
ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up")
out, _, err = runCommandWithOutput(ifCfgCmd)
return out, err
}
func deleteInterface(c *check.C, ifName string) {
ifCmd := exec.Command("ip", "link", "delete", ifName)
out, _, err := runCommandWithOutput(ifCmd)
c.Assert(err, check.IsNil, check.Commentf(out))
flushCmd := exec.Command("iptables", "-t", "nat", "--flush")
out, _, err = runCommandWithOutput(flushCmd)
c.Assert(err, check.IsNil, check.Commentf(out))
flushCmd = exec.Command("iptables", "--flush")
out, _, err = runCommandWithOutput(flushCmd)
c.Assert(err, check.IsNil, check.Commentf(out))
}
func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) {
// TestDaemonBridgeIP Steps
// 1. Delete the existing docker0 Bridge
// 2. Set --bip daemon configuration and start the new Docker Daemon
// 3. Check if the bip config has taken effect using ifconfig and iptables commands
// 4. Launch a Container and make sure the IP-Address is in the expected subnet
// 5. Delete the docker0 Bridge
// 6. Restart the Docker Daemon (via defered action)
// This Restart takes care of bringing docker0 interface back to auto-assigned IP
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
d := s.d
bridgeIp := "192.169.1.1/24"
ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIp)
err := d.StartWithBusybox("--bip", bridgeIp)
c.Assert(err, check.IsNil)
defer d.Restart()
ifconfigSearchString := ip.String()
ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge)
out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd)
c.Assert(err, check.IsNil)
c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true,
check.Commentf("ifconfig output should have contained %q, but was %q",
ifconfigSearchString, out))
ipTablesSearchString := bridgeIPNet.String()
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
out, _, err = runCommandWithOutput(ipTablesCmd)
c.Assert(err, check.IsNil)
c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true,
check.Commentf("iptables output should have contained %q, but was %q",
ipTablesSearchString, out))
out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top")
c.Assert(err, check.IsNil)
containerIp := d.findContainerIP("test")
ip = net.ParseIP(containerIp)
c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
check.Commentf("Container IP-Address must be in the same subnet range : %s",
containerIp))
deleteInterface(c, defaultNetworkBridge)
}
func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) {
if err := s.d.Start(); err != nil {
c.Fatalf("Could not start daemon: %v", err)
}
defer s.d.Restart()
if err := s.d.Stop(); err != nil {
c.Fatalf("Could not stop daemon: %v", err)
}
// now we will change the docker0's IP and then try starting the daemon
bridgeIP := "192.169.100.1/24"
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
ipCmd := exec.Command("ifconfig", "docker0", bridgeIP)
stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd)
if err != nil {
c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr)
}
if err := s.d.Start("--bip", bridgeIP); err != nil {
c.Fatalf("Could not start daemon: %v", err)
}
//check if the iptables contains new bridgeIP MASQUERADE rule
ipTablesSearchString := bridgeIPNet.String()
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
out, _, err := runCommandWithOutput(ipTablesCmd)
if err != nil {
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
}
if !strings.Contains(out, ipTablesSearchString) {
c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out)
}
}
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) {
d := s.d
bridgeName := "external-bridge"
bridgeIp := "192.169.1.1/24"
out, err := createInterface(c, "bridge", bridgeName, bridgeIp)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, bridgeName)
args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"}
err = d.StartWithBusybox(args...)
c.Assert(err, check.IsNil)
defer d.Restart()
for i := 0; i < 4; i++ {
cName := "Container" + strconv.Itoa(i)
out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
if err != nil {
c.Assert(strings.Contains(out, "no available ip addresses"), check.Equals, true,
check.Commentf("Could not run a Container : %s %s", err.Error(), out))
}
}
}
func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) {
d := s.d
ipStr := "192.170.1.1/24"
ip, _, _ := net.ParseCIDR(ipStr)
args := []string{"--ip", ip.String()}
err := d.StartWithBusybox(args...)
c.Assert(err, check.IsNil)
defer d.Restart()
out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
c.Assert(err, check.NotNil,
check.Commentf("Running a container must fail with an invalid --ip option"))
c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true)
ifName := "dummy"
out, err = createInterface(c, "dummy", ifName, ipStr)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, ifName)
_, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
c.Assert(err, check.IsNil)
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
out, _, err = runCommandWithOutput(ipTablesCmd)
c.Assert(err, check.IsNil)
regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String())
matched, _ := regexp.MatchString(regex, out)
c.Assert(matched, check.Equals, true,
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
}
func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) {
d := s.d
bridgeName := "external-bridge"
bridgeIp := "192.169.1.1/24"
out, err := createInterface(c, "bridge", bridgeName, bridgeIp)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, bridgeName)
args := []string{"--bridge", bridgeName, "--icc=false"}
err = d.StartWithBusybox(args...)
c.Assert(err, check.IsNil)
defer d.Restart()
ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
out, _, err = runCommandWithOutput(ipTablesCmd)
c.Assert(err, check.IsNil)
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
matched, _ := regexp.MatchString(regex, out)
c.Assert(matched, check.Equals, true,
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
// Pinging another container must fail with --icc=false
pingContainers(c, d, true)
ipStr := "192.171.1.1/24"
ip, _, _ := net.ParseCIDR(ipStr)
ifName := "icc-dummy"
createInterface(c, "dummy", ifName, ipStr)
// But, Pinging external or a Host interface must succeed
pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String())
runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd}
_, err = d.Cmd("run", runArgs...)
c.Assert(err, check.IsNil)
}
func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) {
d := s.d
bridgeName := "external-bridge"
bridgeIp := "192.169.1.1/24"
out, err := createInterface(c, "bridge", bridgeName, bridgeIp)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, bridgeName)
args := []string{"--bridge", bridgeName, "--icc=false"}
err = d.StartWithBusybox(args...)
c.Assert(err, check.IsNil)
defer d.Restart()
ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
out, _, err = runCommandWithOutput(ipTablesCmd)
c.Assert(err, check.IsNil)
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
matched, _ := regexp.MatchString(regex, out)
c.Assert(matched, check.Equals, true,
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567")
c.Assert(err, check.IsNil, check.Commentf(out))
out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567")
c.Assert(err, check.IsNil, check.Commentf(out))
}
func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) {
bridgeName := "external-bridge"
bridgeIp := "192.169.1.1/24"
out, err := createInterface(c, "bridge", bridgeName, bridgeIp)
c.Assert(err, check.IsNil, check.Commentf(out))
defer deleteInterface(c, bridgeName)
args := []string{"--bridge", bridgeName, "--icc=false"}
err = s.d.StartWithBusybox(args...)
c.Assert(err, check.IsNil)
defer s.d.Restart()
_, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
c.Assert(err, check.IsNil)
_, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
c.Assert(err, check.IsNil)
childIP := s.d.findContainerIP("child")
parentIP := s.d.findContainerIP("parent")
sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}
if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) {
c.Fatal("Iptables rules not found")
}
s.d.Cmd("rm", "--link", "parent/http")
if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) {
c.Fatal("Iptables rules should be removed when unlink")
}
s.d.Cmd("kill", "child")
s.d.Cmd("kill", "parent")
}
func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) {
testRequires(c, NativeExecDriver)
@@ -661,8 +880,8 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) {
if err == nil {
c.Fatalf("Logs should fail with \"none\" driver")
}
if !strings.Contains(out, `\"logs\" command is supported only for \"json-file\" logging driver`) {
c.Fatalf("There should be error about non-json-file driver, got %s", out)
if !strings.Contains(out, `"logs" command is supported only for "json-file" logging driver`) {
c.Fatalf("There should be error about non-json-file driver, got: %s", out)
}
}
@@ -734,7 +953,7 @@ func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) {
}
}
func (s *DockerDaemonSuite) TestDaemonwithwrongkey(c *check.C) {
func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) {
type Config struct {
Crv string `json:"crv"`
D string `json:"d"`
@@ -889,3 +1108,60 @@ func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) {
c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out)
}
}
func pingContainers(c *check.C, d *Daemon, expectFailure bool) {
var dargs []string
if d != nil {
dargs = []string{"--host", d.sock()}
}
args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top")
_, err := runCommand(exec.Command(dockerBinary, args...))
c.Assert(err, check.IsNil)
args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c")
pingCmd := "ping -c 1 %s -W 1"
args = append(args, fmt.Sprintf(pingCmd, "alias1"))
_, err = runCommand(exec.Command(dockerBinary, args...))
if expectFailure {
c.Assert(err, check.NotNil)
} else {
c.Assert(err, check.IsNil)
}
args = append(dargs, "rm", "-f", "container1")
runCommand(exec.Command(dockerBinary, args...))
}
func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) {
c.Assert(s.d.StartWithBusybox(), check.IsNil)
socket := filepath.Join(s.d.folder, "docker.sock")
out, err := s.d.Cmd("run", "-d", "-v", socket+":/sock", "busybox")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
c.Assert(s.d.Restart(), check.IsNil)
}
func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) {
c.Assert(s.d.StartWithBusybox(), check.IsNil)
out, err := s.d.Cmd("run", "-d", "busybox", "top")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
id := strings.TrimSpace(out)
c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil)
c.Assert(s.d.Start(), check.IsNil)
mountOut, err := exec.Command("mount").CombinedOutput()
c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut))
c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, check.Commentf("Something mounted from older daemon start: %s", mountOut))
}
func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) {
c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil)
out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l")
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
c.Assert(strings.Contains(out, "eth0"), check.Equals, false,
check.Commentf("There shouldn't be eth0 in container when network is disabled: %s", out))
}
+3 -1
View File
@@ -40,12 +40,14 @@ func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
// this is a list of files which shouldn't show up in `docker diff`
dockerinitFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerinit", "/.dockerenv"}
containerCount := 5
// we might not run into this problem from the first run, so start a few containers
for i := 0; i < 20; i++ {
for i := 0; i < containerCount; i++ {
containerCmd := `echo foo > /root/bar`
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", containerCmd)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(out, err)
}
+60
View File
@@ -13,6 +13,41 @@ import (
"github.com/go-check/check"
)
func (s *DockerSuite) TestEventsTimestampFormats(c *check.C) {
image := "busybox"
// Start stopwatch, generate an event
time.Sleep(time.Second) // so that we don't grab events from previous test occured in the same second
start := daemonTime(c)
time.Sleep(time.Second) // remote API precision is only a second, wait a while before creating an event
dockerCmd(c, "tag", image, "timestamptest:1")
dockerCmd(c, "rmi", "timestamptest:1")
time.Sleep(time.Second) // so that until > since
end := daemonTime(c)
// List of available time formats to --since
unixTs := func(t time.Time) string { return fmt.Sprintf("%v", t.Unix()) }
rfc3339 := func(t time.Time) string { return t.Format(time.RFC3339) }
// --since=$start must contain only the 'untag' event
for _, f := range []func(time.Time) string{unixTs, rfc3339} {
since, until := f(start), f(end)
cmd := exec.Command(dockerBinary, "events", "--since="+since, "--until="+until)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatalf("docker events cmd failed: %v\nout=%s", err, out)
}
events := strings.Split(strings.TrimSpace(out), "\n")
if len(events) != 2 {
c.Fatalf("unexpected events, was expecting only 2 events tag/untag (since=%s, until=%s) out=%s", since, until, out)
}
if !strings.Contains(out, "untag") {
c.Fatalf("expected 'untag' event not found (since=%s, until=%s) out=%s", since, until, out)
}
}
}
func (s *DockerSuite) TestEventsUntag(c *check.C) {
image := "busybox"
dockerCmd(c, "tag", image, "utest:tag1")
@@ -195,6 +230,31 @@ func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
}
}
func (s *DockerSuite) TestEventsImageTag(c *check.C) {
time.Sleep(time.Second * 2) // because API has seconds granularity
since := daemonTime(c).Unix()
image := "testimageevents:tag"
dockerCmd(c, "tag", "busybox", image)
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, err := runCommandWithOutput(eventsCmd)
c.Assert(err, check.IsNil)
events := strings.Split(strings.TrimSpace(out), "\n")
if len(events) != 1 {
c.Fatalf("was expecting 1 event. out=%s", out)
}
event := strings.TrimSpace(events[0])
expectedStr := image + ": tag"
if !strings.HasSuffix(event, expectedStr) {
c.Fatalf("wrong event format. expected='%s' got=%s", expectedStr, event)
}
}
func (s *DockerSuite) TestEventsImagePull(c *check.C) {
since := daemonTime(c).Unix()
testRequires(c, Network)
-25
View File
@@ -634,28 +634,3 @@ func (s *DockerSuite) TestExecWithUser(c *check.C) {
}
}
func (s *DockerSuite) TestExecWithPrivileged(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
c.Fatal(out, err)
}
cmd := exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sda b 8 0")
out, _, err := runCommandWithOutput(cmd)
if err == nil || !strings.Contains(out, "Operation not permitted") {
c.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed")
}
cmd = exec.Command(dockerBinary, "exec", "--privileged", "parent", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
if actual := strings.TrimSpace(out); actual != "ok" {
c.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out)
}
}
@@ -0,0 +1,24 @@
// +build experimental
package main
import (
"os/exec"
"strings"
"github.com/go-check/check"
)
func (s *DockerSuite) TestExperimentalVersion(c *check.C) {
versionCmd := exec.Command(dockerBinary, "version")
out, _, err := runCommandWithOutput(versionCmd)
if err != nil {
c.Fatalf("failed to execute docker version: %s, %v", out, err)
}
for _, line := range strings.Split(out, "\n") {
if strings.HasPrefix(line, "Client version:") || strings.HasPrefix(line, "Server version:") {
c.Assert(line, check.Matches, "*-experimental")
}
}
}
@@ -12,18 +12,12 @@ import (
func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
containerID := "testexportcontainerandimportimage"
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
runCmd := exec.Command(dockerBinary, "run", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
exportCmd := exec.Command(dockerBinary, "export", containerID)
if out, _, err = runCommandWithOutput(exportCmd); err != nil {
c.Fatalf("failed to export container: %s, %v", out, err)
@@ -37,30 +31,21 @@ func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("output should've been an image id: %s, %v", out, err)
if cleanedImageID == "" {
c.Fatalf("output should have been an image id, got: %s", out)
}
}
// Used to test output flag in the export command
func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
containerID := "testexportcontainerwithoutputandimportimage"
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
runCmd := exec.Command(dockerBinary, "run", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
defer os.Remove("testexp.tar")
exportCmd := exec.Command(dockerBinary, "export", "--output=testexp.tar", containerID)
@@ -81,10 +66,7 @@ func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("output should've been an image id: %s, %v", out, err)
if cleanedImageID == "" {
c.Fatalf("output should have been an image id, got: %s", out)
}
}
+29
View File
@@ -152,3 +152,32 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
}
}
func (s *DockerSuite) TestHelpErrorStderr(c *check.C) {
// If we had a generic CLI test file this one shoudl go in there
cmd := exec.Command(dockerBinary, "boogie")
out, ec, err := runCommandWithOutput(cmd)
if err == nil || ec == 0 {
c.Fatalf("Boogie command should have failed")
}
expected := "docker: 'boogie' is not a docker command. See 'docker --help'.\n"
if out != expected {
c.Fatalf("Bad output from boogie\nGot:%s\nExpected:%s", out, expected)
}
cmd = exec.Command(dockerBinary, "rename", "foo", "bar")
out, ec, err = runCommandWithOutput(cmd)
if err == nil || ec == 0 {
c.Fatalf("Rename should have failed")
}
expected = `Error response from daemon: no such id: foo
Error: failed to rename container named foo
`
if out != expected {
c.Fatalf("Bad output from rename\nGot:%s\nExpected:%s", out, expected)
}
}
+11
View File
@@ -39,3 +39,14 @@ func (s *DockerSuite) TestImportDisplay(c *check.C) {
}
}
func (s *DockerSuite) TestImportBadURL(c *check.C) {
runCmd := exec.Command(dockerBinary, "import", "http://nourl/bad")
out, _, err := runCommandWithOutput(runCmd)
if err == nil {
c.Fatal("import was supposed to fail but didn't")
}
if !strings.Contains(out, "dial tcp") {
c.Fatalf("expected an error msg but didn't get one:\n%s", out)
}
}
+7 -2
View File
@@ -4,6 +4,7 @@ import (
"os/exec"
"strings"
"github.com/docker/docker/utils"
"github.com/go-check/check"
)
@@ -26,12 +27,16 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
"CPUs:",
"Total Memory:",
"Kernel Version:",
"Storage Driver:"}
"Storage Driver:",
}
if utils.ExperimentalBuild() {
stringsToCheck = append(stringsToCheck, "Experimental: true")
}
for _, linePrefix := range stringsToCheck {
if !strings.Contains(out, linePrefix) {
c.Errorf("couldn't find string %v in output", linePrefix)
}
}
}
+18 -27
View File
@@ -12,13 +12,10 @@ import (
func (s *DockerSuite) TestInspectImage(c *check.C) {
imageTest := "emptyfs"
imageTestID := "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158"
imagesCmd := exec.Command(dockerBinary, "inspect", "--format='{{.Id}}'", imageTest)
out, exitCode, err := runCommandWithOutput(imagesCmd)
if exitCode != 0 || err != nil {
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
id, err := inspectField(imageTest, "Id")
c.Assert(err, check.IsNil)
if id := strings.TrimSuffix(out, "\n"); id != imageTestID {
if id != imageTestID {
c.Fatalf("Expected id: %s for image: %s but received id: %s", imageTestID, imageTest, id)
}
@@ -33,33 +30,28 @@ func (s *DockerSuite) TestInspectInt64(c *check.C) {
out = strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", "-f", "{{.HostConfig.Memory}}", out)
inspectOut, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("failed to inspect container: %v, output: %q", err, inspectOut)
}
inspectOut, err := inspectField(out, "HostConfig.Memory")
c.Assert(err, check.IsNil)
if strings.TrimSpace(inspectOut) != "314572800" {
if inspectOut != "314572800" {
c.Fatalf("inspect got wrong value, got: %q, expected: 314572800", inspectOut)
}
}
func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
imageTest := "emptyfs"
imagesCmd := exec.Command(dockerBinary, "inspect", "--format='{{.Size}}'", imageTest)
out, exitCode, err := runCommandWithOutput(imagesCmd)
if exitCode != 0 || err != nil {
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
size, err := strconv.Atoi(strings.TrimSuffix(out, "\n"))
out, err := inspectField(imageTest, "Size")
c.Assert(err, check.IsNil)
size, err := strconv.Atoi(out)
if err != nil {
c.Fatalf("failed to inspect size of the image: %s, %v", out, err)
}
//now see if the size turns out to be the same
formatStr := fmt.Sprintf("--format='{{eq .Size %d}}'", size)
imagesCmd = exec.Command(dockerBinary, "inspect", formatStr, imageTest)
out, exitCode, err = runCommandWithOutput(imagesCmd)
imagesCmd := exec.Command(dockerBinary, "inspect", formatStr, imageTest)
out, exitCode, err := runCommandWithOutput(imagesCmd)
if exitCode != 0 || err != nil {
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
@@ -69,7 +61,8 @@ func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) {
}
func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) {
runCmd := exec.Command("bash", "-c", `echo "blahblah" | docker run -i -a stdin busybox cat`)
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "cat")
runCmd.Stdin = strings.NewReader("blahblah")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
c.Fatalf("failed to run container: %v, output: %q", err, out)
@@ -77,12 +70,10 @@ func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) {
id := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.ExitCode}}'", id)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to inspect container: %s, %v", out, err)
}
exitCode, err := strconv.Atoi(strings.TrimSuffix(out, "\n"))
out, err = inspectField(id, "State.ExitCode")
c.Assert(err, check.IsNil)
exitCode, err := strconv.Atoi(out)
if err != nil {
c.Fatalf("failed to inspect exitcode of the container: %s, %v", out, err)
}
+7 -27
View File
@@ -15,11 +15,7 @@ func (s *DockerSuite) TestKillContainer(c *check.C) {
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
c.Assert(waitRun(cleanedContainerID), check.IsNil)
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
@@ -35,31 +31,22 @@ func (s *DockerSuite) TestKillContainer(c *check.C) {
if strings.Contains(out, cleanedContainerID) {
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestKillofStoppedContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(out, err)
}
c.Assert(err, check.IsNil)
cleanedContainerID := strings.TrimSpace(out)
stopCmd := exec.Command(dockerBinary, "stop", cleanedContainerID)
if out, _, err = runCommandWithOutput(stopCmd); err != nil {
c.Fatalf("failed to stop container: %s, %v", out, err)
}
out, _, err = runCommandWithOutput(stopCmd)
c.Assert(err, check.IsNil, check.Commentf("failed to stop container: %s, %v", out, err))
killCmd := exec.Command(dockerBinary, "kill", "-s", "30", cleanedContainerID)
if _, _, err = runCommandWithOutput(killCmd); err == nil {
c.Fatalf("kill succeeded on a stopped container")
}
deleteContainer(cleanedContainerID)
_, _, err = runCommandWithOutput(killCmd)
c.Assert(err, check.Not(check.IsNil), check.Commentf("Kill succeeded on a stopped container"))
}
func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) {
@@ -70,11 +57,7 @@ func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) {
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
c.Assert(waitRun(cleanedContainerID), check.IsNil)
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
@@ -90,7 +73,4 @@ func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) {
if strings.Contains(out, cleanedContainerID) {
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
}
+21 -28
View File
@@ -10,12 +10,10 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/iptables"
"github.com/go-check/check"
)
func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
@@ -111,31 +109,6 @@ func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
}
func (s *DockerSuite) TestLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) {
testRequires(c, SameHostDaemon)
dockerCmd(c, "run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
childIP := findContainerIP(c, "child")
parentIP := findContainerIP(c, "parent")
sourceRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
destinationRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}
if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) {
c.Fatal("Iptables rules not found")
}
dockerCmd(c, "rm", "--link", "parent/http")
if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) {
c.Fatal("Iptables rules should be removed when unlink")
}
dockerCmd(c, "kill", "child")
dockerCmd(c, "kill", "parent")
}
func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
@@ -252,7 +225,7 @@ func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true"))
if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior.") {
if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior") {
c.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
}
@@ -331,3 +304,23 @@ func (s *DockerSuite) TestLinksEnvs(c *check.C) {
c.Fatalf("Incorrect output: %s", out)
}
}
func (s *DockerSuite) TestLinkShortDefinition(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "shortlinkdef", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
cid := strings.TrimSpace(out)
c.Assert(waitRun(cid), check.IsNil)
runCmd = exec.Command(dockerBinary, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
cid2 := strings.TrimSpace(out)
c.Assert(waitRun(cid2), check.IsNil)
links, err := inspectFieldJSON(cid2, "HostConfig.Links")
c.Assert(err, check.IsNil)
c.Assert(links, check.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]")
}
+128 -21
View File
@@ -1,9 +1,12 @@
package main
import (
"encoding/json"
"fmt"
"io"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
@@ -32,9 +35,6 @@ func (s *DockerSuite) TestLogsContainerSmallerThanPage(c *check.C) {
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
}
// Regression test: When going over the PageSize, it used to panic (gh#4851)
@@ -58,9 +58,6 @@ func (s *DockerSuite) TestLogsContainerBiggerThanPage(c *check.C) {
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
}
// Regression test: When going much over the PageSize, it used to block (gh#4851)
@@ -84,9 +81,6 @@ func (s *DockerSuite) TestLogsContainerMuchBiggerThanPage(c *check.C) {
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
@@ -126,9 +120,6 @@ func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
}
}
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
@@ -157,9 +148,6 @@ func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
if stderr != msg {
c.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
@@ -188,9 +176,6 @@ func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
if stdout != msg {
c.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestLogsTail(c *check.C) {
@@ -240,8 +225,6 @@ func (s *DockerSuite) TestLogsTail(c *check.C) {
if len(lines) != testLen+1 {
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
@@ -272,8 +255,81 @@ func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
case <-time.After(1 * time.Second):
c.Fatal("Following logs is hanged")
}
}
deleteContainer(cleanedContainerID)
func (s *DockerSuite) TestLogsSince(c *check.C) {
name := "testlogssince"
runCmd := exec.Command(dockerBinary, "run", "--name="+name, "busybox", "/bin/sh", "-c", "for i in $(seq 1 3); do sleep 2; echo `date +%s` log$i; done")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("run failed with errors: %s, %v", out, err)
}
log2Line := strings.Split(strings.Split(out, "\n")[1], " ")
t, err := strconv.ParseInt(log2Line[0], 10, 64) // the timestamp log2 is writen
c.Assert(err, check.IsNil)
since := t + 1 // add 1s so log1 & log2 doesn't show up
logsCmd := exec.Command(dockerBinary, "logs", "-t", fmt.Sprintf("--since=%v", since), name)
out, _, err = runCommandWithOutput(logsCmd)
if err != nil {
c.Fatalf("failed to log container: %s, %v", out, err)
}
// Skip 2 seconds
unexpected := []string{"log1", "log2"}
for _, v := range unexpected {
if strings.Contains(out, v) {
c.Fatalf("unexpected log message returned=%v, since=%v\nout=%v", v, since, out)
}
}
// Test with default value specified and parameter omitted
expected := []string{"log1", "log2", "log3"}
for _, cmd := range []*exec.Cmd{
exec.Command(dockerBinary, "logs", "-t", name),
exec.Command(dockerBinary, "logs", "-t", "--since=0", name),
} {
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatalf("failed to log container: %s, %v", out, err)
}
for _, v := range expected {
if !strings.Contains(out, v) {
c.Fatalf("'%v' does not contain=%v\nout=%s", cmd.Args, v, out)
}
}
}
}
func (s *DockerSuite) TestLogsSinceFutureFollow(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", `for i in $(seq 1 5); do date +%s; sleep 1; done`)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
now := daemonTime(c).Unix()
since := now + 2
logCmd := exec.Command(dockerBinary, "logs", "-f", fmt.Sprintf("--since=%v", since), cleanedContainerID)
out, _, err = runCommandWithOutput(logCmd)
if err != nil {
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines := strings.Split(strings.TrimSpace(out), "\n")
if len(lines) == 0 {
c.Fatal("got no log lines")
}
for _, v := range lines {
ts, err := strconv.ParseInt(v, 10, 64)
if err != nil {
c.Fatalf("cannot parse timestamp output from log: '%v'\nout=%s", v, out)
}
if ts < since {
c.Fatalf("earlier log found. since=%v logdate=%v", since, ts)
}
}
}
// Regression test for #8832
@@ -318,3 +374,54 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
}
}
func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
type info struct {
NGoroutines int
}
getNGoroutines := func() int {
var i info
status, b, err := sockRequest("GET", "/info", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, 200)
c.Assert(json.Unmarshal(b, &i), check.IsNil)
return i.NGoroutines
}
nroutines := getNGoroutines()
cmd := exec.Command(dockerBinary, "logs", "-f", id)
r, w := io.Pipe()
cmd.Stdout = w
c.Assert(cmd.Start(), check.IsNil)
// Make sure pipe is written to
chErr := make(chan error)
go func() {
b := make([]byte, 1)
_, err := r.Read(b)
chErr <- err
}()
c.Assert(<-chErr, check.IsNil)
c.Assert(cmd.Process.Kill(), check.IsNil)
// NGoroutines is not updated right away, so we need to wait before failing
t := time.After(30 * time.Second)
for {
select {
case <-t:
if n := getNGoroutines(); n > nroutines {
c.Fatalf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n)
}
default:
if n := getNGoroutines(); n <= nroutines {
return
}
time.Sleep(200 * time.Millisecond)
}
}
}
+69 -19
View File
@@ -9,9 +9,22 @@ import (
"github.com/go-check/check"
)
func (s *DockerSuite) TestNetworkNat(c *check.C) {
testRequires(c, SameHostDaemon, NativeExecDriver)
func startServerContainer(c *check.C, proto string, port int) string {
pStr := fmt.Sprintf("%d:%d", port, port)
bCmd := fmt.Sprintf("nc -lp %d && echo bye", port)
cmd := []string{"-d", "-p", pStr, "busybox", "sh", "-c", bCmd}
if proto == "udp" {
cmd = append(cmd, "-u")
}
name := "server"
if err := waitForContainer(name, cmd...); err != nil {
c.Fatalf("Failed to launch server container: %v", err)
}
return name
}
func getExternalAddress(c *check.C) net.IP {
iface, err := net.InterfaceByName("eth0")
if err != nil {
c.Skip(fmt.Sprintf("Test not running with `make test`. Interface eth0 not found: %v", err))
@@ -27,35 +40,72 @@ func (s *DockerSuite) TestNetworkNat(c *check.C) {
c.Fatalf("Error retrieving the up for eth0: %s", err)
}
runCmd := exec.Command(dockerBinary, "run", "-dt", "-p", "8080:8080", "busybox", "nc", "-lp", "8080")
return ifaceIP
}
func getContainerLogs(c *check.C, containerID string) string {
runCmd := exec.Command(dockerBinary, "logs", containerID)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(out, err)
}
return strings.Trim(out, "\r\n")
}
cleanedContainerID := strings.TrimSpace(out)
func getContainerStatus(c *check.C, containerID string) string {
out, err := inspectField(containerID, "State.Running")
c.Assert(err, check.IsNil)
return out
}
runCmd = exec.Command(dockerBinary, "run", "busybox", "sh", "-c", fmt.Sprintf("echo hello world | nc -w 30 %s 8080", ifaceIP))
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(out, err)
func (s *DockerSuite) TestNetworkNat(c *check.C) {
testRequires(c, SameHostDaemon, NativeExecDriver)
srv := startServerContainer(c, "tcp", 8080)
// Spawn a new container which connects to the server through the
// interface address.
endpoint := getExternalAddress(c)
runCmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", fmt.Sprintf("echo hello world | nc -w 30 %s 8080", endpoint))
if out, _, err := runCommandWithOutput(runCmd); err != nil {
c.Fatalf("Failed to connect to server: %v (output: %q)", err, string(out))
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to retrieve logs for container: %s, %v", out, err)
result := getContainerLogs(c, srv)
// Ideally we'd like to check for "hello world" but sometimes
// nc doesn't show the data it received so instead let's look for
// the output of the 'echo bye' that should be printed once
// the nc command gets a connection
expected := "bye"
if !strings.Contains(result, expected) {
c.Fatalf("Unexpected output. Expected: %q, received: %q", expected, result)
}
}
out = strings.Trim(out, "\r\n")
func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
testRequires(c, SameHostDaemon, NativeExecDriver)
if expected := "hello world"; out != expected {
c.Fatalf("Unexpected output. Expected: %q, received: %q for iface %s", expected, out, ifaceIP)
srv := startServerContainer(c, "tcp", 8081)
// Attempt to connect from the host to the listening container.
conn, err := net.Dial("tcp", "localhost:8081")
if err != nil {
c.Fatalf("Failed to connect to container (%v)", err)
}
if _, err := conn.Write([]byte("hello world\n")); err != nil {
c.Fatal(err)
}
conn.Close()
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
c.Fatalf("failed to kill container: %s, %v", out, err)
result := getContainerLogs(c, srv)
// Ideally we'd like to check for "hello world" but sometimes
// nc doesn't show the data it received so instead let's look for
// the output of the 'echo bye' that should be printed once
// the nc command gets a connection
expected := "bye"
if !strings.Contains(result, expected) {
c.Fatalf("Unexpected output. Expected: %q, received: %q", expected, result)
}
}
+15 -1
View File
@@ -304,7 +304,7 @@ func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
}
expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
foundSize := lines[1][sizeIndex:]
if foundSize != expectedSize {
if !strings.Contains(foundSize, expectedSize) {
c.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
}
@@ -666,3 +666,17 @@ func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
}
}
func (s *DockerSuite) TestPsWithSize(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "sizetest", "busybox", "top"))
if err != nil {
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "ps", "--size"))
if err != nil {
c.Fatal(out, err)
}
if !strings.Contains(out, "virtual") {
c.Fatalf("docker ps with --size should show virtual size of container")
}
}
+1 -1
View File
@@ -1,6 +1,7 @@
package main
import (
"archive/tar"
"fmt"
"io/ioutil"
"os"
@@ -8,7 +9,6 @@ import (
"strings"
"time"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/go-check/check"
)
+10 -30
View File
@@ -112,11 +112,8 @@ func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
c.Errorf("expect 1 volume received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumes, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(volumes, err)
}
volumes, err := inspectField(cleanedContainerID, ".Volumes")
c.Assert(err, check.IsNil)
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
@@ -133,15 +130,10 @@ func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
c.Errorf("expect 1 volume after restart received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(volumesAfterRestart, err)
}
volumesAfterRestart, err := inspectField(cleanedContainerID, ".Volumes")
c.Assert(err, check.IsNil)
if volumes != volumesAfterRestart {
volumes = strings.Trim(volumes, " \n\r")
volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
c.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
}
@@ -157,9 +149,7 @@ func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
c.Fatal(err, out)
}
c.Assert(err, check.IsNil)
if name != "no" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "no")
}
@@ -176,17 +166,13 @@ func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
c.Fatal(err, out)
}
c.Assert(err, check.IsNil)
if name != "always" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "always")
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
// MaximumRetryCount=0 if the restart policy is always
if MaximumRetryCount != "0" {
@@ -205,9 +191,7 @@ func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
c.Fatal(err, out)
}
c.Assert(err, check.IsNil)
if name != "on-failure" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
}
@@ -226,16 +210,12 @@ func (s *DockerSuite) TestContainerRestartwithGoodContainer(c *check.C) {
c.Fatal(err)
}
count, err := inspectField(id, "RestartCount")
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
if count != "0" {
c.Fatalf("Container was restarted %s times, expected %d", count, 0)
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
if MaximumRetryCount != "3" {
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
}
+2 -13
View File
@@ -1,7 +1,6 @@
package main
import (
"net/http"
"os"
"os/exec"
"strings"
@@ -54,16 +53,6 @@ func (s *DockerSuite) TestRmRunningContainer(c *check.C) {
}
func (s *DockerSuite) TestRmRunningContainerCheckError409(c *check.C) {
createRunningContainer(c, "foo")
endpoint := "/containers/foo"
status, _, err := sockRequest("DELETE", endpoint, nil)
c.Assert(status, check.Equals, http.StatusConflict)
c.Assert(err, check.IsNil)
}
func (s *DockerSuite) TestRmForceRemoveRunningContainer(c *check.C) {
createRunningContainer(c, "foo")
@@ -116,8 +105,8 @@ func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "unknown")); err == nil {
c.Fatal("Expected error on rm unknown container, got none")
} else if !strings.Contains(out, "failed to remove one or more containers") {
c.Fatalf("Expected output to contain 'failed to remove one or more containers', got %q", out)
} else if !strings.Contains(out, "failed to remove containers") {
c.Fatalf("Expected output to contain 'failed to remove containers', got %q", out)
}
}
+2 -5
View File
@@ -35,9 +35,6 @@ func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
if !strings.Contains(images, "busybox") {
c.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
}
deleteContainer(cleanedContainerID)
}
func (s *DockerSuite) TestRmiTag(c *check.C) {
@@ -101,8 +98,8 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
c.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
}
}
out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox-test")
imgID := strings.TrimSpace(out)
imgID, err := inspectField("busybox-test", "Id")
c.Assert(err, check.IsNil)
// first checkout without force it fails
runCmd = exec.Command(dockerBinary, "rmi", imgID)
File diff suppressed because it is too large Load Diff
+12 -38
View File
@@ -15,29 +15,22 @@ import (
// save a repo using gz compression and try to load it using stdout
func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
name := "test-save-xz-and-load-repo-stdout"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
repoName := "foobar-save-load-test-xz-gz"
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
commitCmd := exec.Command(dockerBinary, "commit", name, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
inspectCmd := exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
@@ -71,29 +64,22 @@ func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
// save a repo using xz+gz compression and try to load it using stdout
func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
name := "test-save-xz-gz-and-load-repo-stdout"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
repoName := "foobar-save-load-test-xz-gz"
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
commitCmd := exec.Command(dockerBinary, "commit", name, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
inspectCmd := exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
@@ -121,10 +107,6 @@ func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
if err == nil {
c.Fatalf("the repo should not exist: %v", after)
}
deleteContainer(cleanedContainerID)
deleteImages(repoName)
}
func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
@@ -207,28 +189,21 @@ func (s *DockerSuite) TestSaveImageId(c *check.C) {
// save a repo and try to load it using flags
func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
name := "test-save-and-load-repo-flags"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
repoName := "foobar-save-load-test"
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
commitCmd := exec.Command(dockerBinary, "commit", name, repoName)
deleteImages(repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
inspectCmd := exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
@@ -251,7 +226,6 @@ func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
if before != after {
c.Fatalf("inspect is not the same after a save / load")
}
}
func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
@@ -4,10 +4,9 @@ package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
"github.com/docker/docker/vendor/src/github.com/kr/pty"
"github.com/go-check/check"
@@ -15,43 +14,45 @@ import (
// save a repo and try to load it using stdout
func (s *DockerSuite) TestSaveAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
name := "test-save-and-load-repo-stdout"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
repoName := "foobar-save-load-test"
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
commitCmd := exec.Command(dockerBinary, "commit", name, repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
inspectCmd := exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
}
saveCmdTemplate := `%v save %v > /tmp/foobar-save-load-test.tar`
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName)
saveCmd := exec.Command("bash", "-c", saveCmdFinal)
if out, _, err = runCommandWithOutput(saveCmd); err != nil {
c.Fatalf("failed to save repo: %s, %v", out, err)
tmpFile, err := ioutil.TempFile("", "foobar-save-load-test.tar")
c.Assert(err, check.IsNil)
defer os.Remove(tmpFile.Name())
saveCmd := exec.Command(dockerBinary, "save", repoName)
saveCmd.Stdout = tmpFile
if _, err = runCommand(saveCmd); err != nil {
c.Fatalf("failed to save repo: %v", err)
}
tmpFile, err = os.Open(tmpFile.Name())
c.Assert(err, check.IsNil)
deleteImages(repoName)
loadCmdFinal := `cat /tmp/foobar-save-load-test.tar | docker load`
loadCmd := exec.Command("bash", "-c", loadCmdFinal)
loadCmd := exec.Command(dockerBinary, "load")
loadCmd.Stdin = tmpFile
if out, _, err = runCommandWithOutput(loadCmd); err != nil {
c.Fatalf("failed to load repo: %s, %v", out, err)
}
@@ -66,11 +67,8 @@ func (s *DockerSuite) TestSaveAndLoadRepoStdout(c *check.C) {
c.Fatalf("inspect is not the same after a save / load")
}
deleteContainer(cleanedContainerID)
deleteImages(repoName)
os.Remove("/tmp/foobar-save-load-test.tar")
pty, tty, err := pty.Open()
if err != nil {
c.Fatalf("Could not open pty: %v", err)
+10
View File
@@ -63,6 +63,16 @@ func (s *DockerSuite) TestSearchCmdOptions(c *check.C) {
c.Fatalf("failed to search on the central registry: %s, %v", outSearchCmd, err)
}
searchCmdNotrunc := exec.Command(dockerBinary, "search", "--no-trunc=true", "busybox")
outSearchCmdNotrunc, _, err := runCommandWithOutput(searchCmdNotrunc)
if err != nil {
c.Fatalf("failed to search on the central registry: %s, %v", outSearchCmdNotrunc, err)
}
if len(outSearchCmd) > len(outSearchCmdNotrunc) {
c.Fatalf("The no-trunc option can't take effect.")
}
searchCmdautomated := exec.Command(dockerBinary, "search", "--automated=true", "busybox")
outSearchCmdautomated, exitCode, err := runCommandWithOutput(searchCmdautomated) //The busybox is a busybox base image, not an AUTOMATED image.
if err != nil || exitCode != 0 {
+8 -50
View File
@@ -98,9 +98,7 @@ func (s *DockerSuite) TestStartRecordError(c *check.C) {
// when container runs successfully, we should not have state.Error
dockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
stateErr, err := inspectField("test", "State.Error")
if err != nil {
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
c.Assert(err, check.IsNil)
if stateErr != "" {
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
@@ -111,9 +109,7 @@ func (s *DockerSuite) TestStartRecordError(c *check.C) {
c.Fatalf("Expected error but got none, output %q", out)
}
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
c.Fatalf("Failed to inspect %q state's error, got error %q", "test2", err)
}
c.Assert(err, check.IsNil)
expected := "port is already allocated"
if stateErr == "" || !strings.Contains(stateErr, expected) {
c.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
@@ -123,41 +119,13 @@ func (s *DockerSuite) TestStartRecordError(c *check.C) {
dockerCmd(c, "stop", "test")
dockerCmd(c, "start", "test2")
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
c.Assert(err, check.IsNil)
if stateErr != "" {
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
}
// gh#8726: a failed Start() breaks --volumes-from on subsequent Start()'s
func (s *DockerSuite) TestStartVolumesFromFailsCleanly(c *check.C) {
// Create the first data volume
dockerCmd(c, "run", "-d", "--name", "data_before", "-v", "/foo", "busybox")
// Expect this to fail because the data test after contaienr doesn't exist yet
if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "consumer", "--volumes-from", "data_before", "--volumes-from", "data_after", "busybox")); err == nil {
c.Fatal("Expected error but got none")
}
// Create the second data volume
dockerCmd(c, "run", "-d", "--name", "data_after", "-v", "/bar", "busybox")
// Now, all the volumes should be there
dockerCmd(c, "start", "consumer")
// Check that we have the volumes we want
out, _ := dockerCmd(c, "inspect", "--format='{{ len .Volumes }}'", "consumer")
nVolumes := strings.Trim(out, " \r\n'")
if nVolumes != "2" {
c.Fatalf("Missing volumes: expected 2, got %s", nVolumes)
}
}
func (s *DockerSuite) TestStartPausedContainer(c *check.C) {
defer unpauseAllContainers()
@@ -196,12 +164,8 @@ func (s *DockerSuite) TestStartMultipleContainers(c *check.C) {
if out, _, err := runCommandWithOutput(cmd); err != nil {
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", "parent")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
out, err := inspectField("parent", "State.Running")
c.Assert(err, check.IsNil)
if out != "false" {
c.Fatal("Container should be stopped")
}
@@ -215,12 +179,8 @@ func (s *DockerSuite) TestStartMultipleContainers(c *check.C) {
}
for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
out, err := inspectField(container, "State.Running")
c.Assert(err, check.IsNil)
if out != expected {
c.Fatal("Container running state wrong")
}
@@ -260,12 +220,10 @@ func (s *DockerSuite) TestStartAttachMultipleContainers(c *check.C) {
// confirm the state of all the containers be stopped
for container, expected := range map[string]string{"test1": "false", "test2": "false", "test3": "false"} {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err := runCommandWithOutput(cmd)
out, err := inspectField(container, "State.Running")
if err != nil {
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != expected {
c.Fatal("Container running state wrong")
}
@@ -0,0 +1,249 @@
// +build experimental
// +build !windows
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"github.com/go-check/check"
)
func init() {
check.Suite(&DockerExternalVolumeSuite{
ds: &DockerSuite{},
})
}
type eventCounter struct {
activations int
creations int
removals int
mounts int
unmounts int
paths int
}
type DockerExternalVolumeSuite struct {
server *httptest.Server
ds *DockerSuite
d *Daemon
ec *eventCounter
}
func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) {
s.d = NewDaemon(c)
s.ds.SetUpTest(c)
s.ec = &eventCounter{}
}
func (s *DockerExternalVolumeSuite) TearDownTest(c *check.C) {
s.d.Stop()
s.ds.TearDownTest(c)
}
func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
mux := http.NewServeMux()
s.server = httptest.NewServer(mux)
type pluginRequest struct {
name string
}
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
s.ec.activations++
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, `{"Implements": ["VolumeDriver"]}`)
})
mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) {
s.ec.creations++
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, `{}`)
})
mux.HandleFunc("/VolumeDriver.Remove", func(w http.ResponseWriter, r *http.Request) {
s.ec.removals++
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, `{}`)
})
mux.HandleFunc("/VolumeDriver.Path", func(w http.ResponseWriter, r *http.Request) {
s.ec.paths++
var pr pluginRequest
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
http.Error(w, err.Error(), 500)
}
p := hostVolumePath(pr.name)
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, fmt.Sprintf("{\"Mountpoint\": \"%s\"}", p))
})
mux.HandleFunc("/VolumeDriver.Mount", func(w http.ResponseWriter, r *http.Request) {
s.ec.mounts++
var pr pluginRequest
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
http.Error(w, err.Error(), 500)
}
p := hostVolumePath(pr.name)
if err := os.MkdirAll(p, 0755); err != nil {
http.Error(w, err.Error(), 500)
}
if err := ioutil.WriteFile(filepath.Join(p, "test"), []byte(s.server.URL), 0644); err != nil {
http.Error(w, err.Error(), 500)
}
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, fmt.Sprintf("{\"Mountpoint\": \"%s\"}", p))
})
mux.HandleFunc("/VolumeDriver.Unmount", func(w http.ResponseWriter, r *http.Request) {
s.ec.unmounts++
var pr pluginRequest
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
http.Error(w, err.Error(), 500)
}
p := hostVolumePath(pr.name)
if err := os.RemoveAll(p); err != nil {
http.Error(w, err.Error(), 500)
}
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
fmt.Fprintln(w, `{}`)
})
if err := os.MkdirAll("/usr/share/docker/plugins", 0755); err != nil {
c.Fatal(err)
}
if err := ioutil.WriteFile("/usr/share/docker/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644); err != nil {
c.Fatal(err)
}
}
func (s *DockerExternalVolumeSuite) TearDownSuite(c *check.C) {
s.server.Close()
if err := os.RemoveAll("/usr/share/docker/plugins"); err != nil {
c.Fatal(err)
}
}
func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriver(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test")
if err != nil {
c.Fatal(err)
}
if !strings.Contains(out, s.server.URL) {
c.Fatalf("External volume mount failed. Output: %s\n", out)
}
p := hostVolumePath("external-volume-test")
_, err = os.Lstat(p)
if err == nil {
c.Fatalf("Expected error checking volume path in host: %s\n", p)
}
if !os.IsNotExist(err) {
c.Fatalf("Expected volume path in host to not exist: %s, %v\n", p, err)
}
c.Assert(s.ec.activations, check.Equals, 1)
c.Assert(s.ec.creations, check.Equals, 1)
c.Assert(s.ec.removals, check.Equals, 1)
c.Assert(s.ec.mounts, check.Equals, 1)
c.Assert(s.ec.unmounts, check.Equals, 1)
}
func (s *DockerExternalVolumeSuite) TestStartExternalVolumeUnnamedDriver(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test")
if err != nil {
c.Fatal(err)
}
if !strings.Contains(out, s.server.URL) {
c.Fatalf("External volume mount failed. Output: %s\n", out)
}
c.Assert(s.ec.activations, check.Equals, 1)
c.Assert(s.ec.creations, check.Equals, 1)
c.Assert(s.ec.removals, check.Equals, 1)
c.Assert(s.ec.mounts, check.Equals, 1)
c.Assert(s.ec.unmounts, check.Equals, 1)
}
func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverVolumesFrom(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
if _, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest"); err != nil {
c.Fatal(err)
}
if _, err := s.d.Cmd("run", "--rm", "--volumes-from", "vol-test1", "--name", "vol-test2", "busybox", "ls", "/tmp"); err != nil {
c.Fatal(err)
}
if _, err := s.d.Cmd("rm", "-f", "vol-test1"); err != nil {
c.Fatal(err)
}
c.Assert(s.ec.activations, check.Equals, 1)
c.Assert(s.ec.creations, check.Equals, 2)
c.Assert(s.ec.removals, check.Equals, 1)
c.Assert(s.ec.mounts, check.Equals, 2)
c.Assert(s.ec.unmounts, check.Equals, 2)
}
func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverDeleteContainer(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
if _, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest"); err != nil {
c.Fatal(err)
}
if _, err := s.d.Cmd("rm", "-fv", "vol-test1"); err != nil {
c.Fatal(err)
}
c.Assert(s.ec.activations, check.Equals, 1)
c.Assert(s.ec.creations, check.Equals, 1)
c.Assert(s.ec.removals, check.Equals, 1)
c.Assert(s.ec.mounts, check.Equals, 1)
c.Assert(s.ec.unmounts, check.Equals, 1)
}
func hostVolumePath(name string) string {
return fmt.Sprintf("/var/lib/docker/volumes/%s", name)
}
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"os/exec"
"strings"
"time"
"github.com/go-check/check"
)
func (s *DockerSuite) TestCliStatsNoStream(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "top"))
if err != nil {
c.Fatalf("Error on container creation: %v, output: %s", err, out)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
c.Fatalf("error waiting for container to start: %v", err)
}
statsCmd := exec.Command(dockerBinary, "stats", "--no-stream", id)
chErr := make(chan error)
go func() {
chErr <- statsCmd.Run()
}()
select {
case err := <-chErr:
if err != nil {
c.Fatalf("Error running stats: %v", err)
}
case <-time.After(2 * time.Second):
statsCmd.Process.Kill()
c.Fatalf("stats did not return immediately when not streaming")
}
}
+28 -9
View File
@@ -22,15 +22,10 @@ func (s *DockerSuite) TestTagUnprefixedRepoByName(c *check.C) {
// tagging an image by ID in a new unprefixed repo should work
func (s *DockerSuite) TestTagUnprefixedRepoByID(c *check.C) {
getIDCmd := exec.Command(dockerBinary, "inspect", "-f", "{{.Id}}", "busybox")
out, _, err := runCommandWithOutput(getIDCmd)
if err != nil {
c.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
tagCmd := exec.Command(dockerBinary, "tag", cleanedImageID, "testfoobarbaz")
if out, _, err = runCommandWithOutput(tagCmd); err != nil {
imageID, err := inspectField("busybox", "Id")
c.Assert(err, check.IsNil)
tagCmd := exec.Command(dockerBinary, "tag", imageID, "testfoobarbaz")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
c.Fatal(out, err)
}
}
@@ -116,6 +111,30 @@ func (s *DockerSuite) TestTagExistedNameWithForce(c *check.C) {
}
}
func (s *DockerSuite) TestTagWithSuffixHyphen(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
// test repository name begin with '-'
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "-busybox:test")
out, _, err := runCommandWithOutput(tagCmd)
if err == nil || !strings.Contains(out, "Invalid repository name (-busybox). Cannot begin or end with a hyphen") {
c.Fatal("tag a name begin with '-' should failed")
}
// test namespace name begin with '-'
tagCmd = exec.Command(dockerBinary, "tag", "busybox:latest", "-test/busybox:test")
out, _, err = runCommandWithOutput(tagCmd)
if err == nil || !strings.Contains(out, "Invalid namespace name (-test). Cannot begin or end with a hyphen") {
c.Fatal("tag a name begin with '-' should failed")
}
// test index name begin wiht '-'
tagCmd = exec.Command(dockerBinary, "tag", "busybox:latest", "-index:5000/busybox:test")
out, _, err = runCommandWithOutput(tagCmd)
if err == nil || !strings.Contains(out, "Invalid index name (-index:5000). Cannot begin or end with a hyphen") {
c.Fatal("tag a name begin with '-' should failed")
}
}
// ensure tagging using official names works
// ensure all tags result in the same name
func (s *DockerSuite) TestTagOfficialNames(c *check.C) {
-4
View File
@@ -54,8 +54,6 @@ func (s *DockerSuite) TestTopNonPrivileged(c *check.C) {
c.Fatalf("failed to kill container: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
if !strings.Contains(out1, "top") && !strings.Contains(out2, "top") {
c.Fatal("top should've listed `top` in the process list, but failed twice")
} else if !strings.Contains(out1, "top") {
@@ -92,8 +90,6 @@ func (s *DockerSuite) TestTopPrivileged(c *check.C) {
c.Fatalf("failed to kill container: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
if !strings.Contains(out1, "top") && !strings.Contains(out2, "top") {
c.Fatal("top should've listed `top` in the process list, but failed twice")
} else if !strings.Contains(out1, "top") {
+25 -19
View File
@@ -1,6 +1,7 @@
package main
import (
"bytes"
"os/exec"
"strings"
"time"
@@ -20,12 +21,8 @@ func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
status := "true"
for i := 0; status != "false"; i++ {
runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.Running}}'", containerID)
status, _, err = runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(status, err)
}
status = strings.TrimSpace(status)
status, err = inspectField(containerID, "State.Running")
c.Assert(err, check.IsNil)
time.Sleep(time.Second)
if i >= 60 {
@@ -44,7 +41,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
// blocking wait with 0 exit code
func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' SIGTERM; while true; do sleep 0.01; done")
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 0' TERM; while true; do sleep 0.01; done")
containerID := strings.TrimSpace(out)
if err := waitRun(containerID); err != nil {
@@ -83,12 +80,8 @@ func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
status := "true"
for i := 0; status != "false"; i++ {
runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.Running}}'", containerID)
status, _, err = runCommandWithOutput(runCmd)
if err != nil {
c.Fatal(status, err)
}
status = strings.TrimSpace(status)
status, err = inspectField(containerID, "State.Running")
c.Assert(err, check.IsNil)
time.Sleep(time.Second)
if i >= 60 {
@@ -107,7 +100,7 @@ func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
// blocking wait with random exit code
func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "trap 'exit 99' SIGTERM; while true; do sleep 0.01; done")
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "trap 'exit 99' TERM; while true; do sleep 0.01; done")
containerID := strings.TrimSpace(out)
if err := waitRun(containerID); err != nil {
c.Fatal(err)
@@ -116,21 +109,34 @@ func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
c.Fatal(err)
}
chWait := make(chan string)
chWait := make(chan error)
waitCmd := exec.Command(dockerBinary, "wait", containerID)
waitCmdOut := bytes.NewBuffer(nil)
waitCmd.Stdout = waitCmdOut
if err := waitCmd.Start(); err != nil {
c.Fatal(err)
}
go func() {
out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID))
chWait <- out
chWait <- waitCmd.Wait()
}()
time.Sleep(100 * time.Millisecond)
dockerCmd(c, "stop", containerID)
select {
case status := <-chWait:
case err := <-chWait:
if err != nil {
c.Fatal(err)
}
status, err := waitCmdOut.ReadString('\n')
if err != nil {
c.Fatal(err)
}
if strings.TrimSpace(status) != "99" {
c.Fatalf("expected exit 99, got %s", status)
}
case <-time.After(2 * time.Second):
waitCmd.Process.Kill()
c.Fatal("timeout waiting for `docker wait` to exit")
}
}
-1
View File
@@ -18,7 +18,6 @@ var (
dockerBasePath = "/var/lib/docker"
volumesConfigPath = dockerBasePath + "/volumes"
volumesStoragePath = dockerBasePath + "/vfs/dir"
containerStoragePath = dockerBasePath + "/containers"
runtimePath = "/var/run/docker"
+27 -4
View File
@@ -37,6 +37,16 @@ type Daemon struct {
storageDriver string
execDriver string
wait chan error
userlandProxy bool
}
func enableUserlandProxy() bool {
if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
if val, err := strconv.ParseBool(env); err != nil {
return val
}
}
return true
}
// NewDaemon returns a Daemon instance to be used for testing.
@@ -48,7 +58,7 @@ func NewDaemon(c *check.C) *Daemon {
c.Fatal("Please set the DEST environment variable")
}
dir := filepath.Join(dest, fmt.Sprintf("daemon%d", time.Now().UnixNano()%100000000))
dir := filepath.Join(dest, fmt.Sprintf("d%d", time.Now().UnixNano()%100000000))
daemonFolder, err := filepath.Abs(dir)
if err != nil {
c.Fatalf("Could not make %q an absolute path: %v", dir, err)
@@ -58,11 +68,19 @@ func NewDaemon(c *check.C) *Daemon {
c.Fatalf("Could not create %s/graph directory", daemonFolder)
}
userlandProxy := true
if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
if val, err := strconv.ParseBool(env); err != nil {
userlandProxy = val
}
}
return &Daemon{
c: c,
folder: daemonFolder,
storageDriver: os.Getenv("DOCKER_GRAPHDRIVER"),
execDriver: os.Getenv("DOCKER_EXECDRIVER"),
userlandProxy: userlandProxy,
}
}
@@ -79,6 +97,7 @@ func (d *Daemon) Start(arg ...string) error {
"--daemon",
"--graph", fmt.Sprintf("%s/graph", d.folder),
"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
}
// If we don't explicitly set the log-level or debug flag(-D) then
@@ -570,8 +589,9 @@ func dockerCmdInDirWithTimeout(timeout time.Duration, path string, args ...strin
return out, status, err
}
func findContainerIP(c *check.C, id string) string {
cmd := exec.Command(dockerBinary, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
func findContainerIP(c *check.C, id string, vargs ...string) string {
args := append(vargs, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
cmd := exec.Command(dockerBinary, args...)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
@@ -580,6 +600,10 @@ func findContainerIP(c *check.C, id string) string {
return strings.Trim(out, " \r\n'")
}
func (d *Daemon) findContainerIP(id string) string {
return findContainerIP(d.c, id, "--host", d.sock())
}
func getContainerCount() (int, error) {
const containers = "Containers:"
@@ -663,7 +687,6 @@ func fakeContextAddDockerfile(ctx *FakeContext, dockerfile string) error {
func fakeContext(dockerfile string, files map[string]string) (*FakeContext, error) {
ctx, err := fakeContextWithFiles(files)
if err != nil {
ctx.Close()
return nil, err
}
if err := fakeContextAddDockerfile(ctx, dockerfile); err != nil {
+8 -1
View File
@@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os/exec"
@@ -44,6 +45,13 @@ var (
},
"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
}
Apparmor = TestRequirement{
func() bool {
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
return err == nil && len(buf) > 1 && buf[0] == 'Y'
},
"Test requires apparmor is enabled.",
}
RegistryHosting = TestRequirement{
func() bool {
// for now registry binary is built only if we're running inside
@@ -78,7 +86,6 @@ var (
},
"Test requires the native (libcontainer) exec driver.",
}
NotOverlay = TestRequirement{
func() bool {
cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
+2 -11
View File
@@ -1,6 +1,7 @@
package main
import (
"archive/tar"
"bytes"
"encoding/json"
"errors"
@@ -17,13 +18,12 @@ import (
"time"
"github.com/docker/docker/pkg/stringutils"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
)
func getExitCode(err error) (int, error) {
exitCode := 0
if exiterr, ok := err.(*exec.ExitError); ok {
if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok {
return procExit.ExitStatus(), nil
}
}
@@ -295,15 +295,6 @@ func fileServer(files map[string]string) (*FileServer, error) {
}, nil
}
func copyWithCP(source, target string) error {
copyCmd := exec.Command("cp", "-rp", source, target)
out, exitCode, err := runCommandWithOutput(copyCmd)
if err != nil || exitCode != 0 {
return fmt.Errorf("failed to copy: error: %q ,output: %q", err, out)
}
return nil
}
// randomUnixTmpDirPath provides a temporary unix path with rand string appended.
// does not create or checks if it exists.
func randomUnixTmpDirPath(s string) string {