mirror of
https://github.com/clearlinux/docker.git
synced 2026-09-06 21:51:33 +00:00
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:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
@@ -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\"]")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ var (
|
||||
|
||||
dockerBasePath = "/var/lib/docker"
|
||||
volumesConfigPath = dockerBasePath + "/volumes"
|
||||
volumesStoragePath = dockerBasePath + "/vfs/dir"
|
||||
containerStoragePath = dockerBasePath + "/containers"
|
||||
|
||||
runtimePath = "/var/run/docker"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user