Merge pull request #21931 from tiborvass/cherry-picks-1.11.0-rc5
Cherry picks 1.11.0 rc5
diff --git a/container/container.go b/container/container.go
index c999162..58892e7 100644
--- a/container/container.go
+++ b/container/container.go
@@ -909,6 +909,7 @@
func (container *Container) RestartManager(reset bool) restartmanager.RestartManager {
if reset {
container.RestartCount = 0
+ container.restartManager = nil
}
if container.restartManager == nil {
container.restartManager = restartmanager.New(container.HostConfig.RestartPolicy)
diff --git a/contrib/completion/zsh/_docker b/contrib/completion/zsh/_docker
index 1351ae9..cb007b9 100644
--- a/contrib/completion/zsh/_docker
+++ b/contrib/completion/zsh/_docker
@@ -216,7 +216,7 @@
gelf_options=("env" "gelf-address" "gelf-compression-level" "gelf-compression-type" "labels" "tag")
journald_options=("env" "labels" "tag")
json_file_options=("env" "labels" "max-file" "max-size")
- syslog_options=("syslog-address" "syslog-tls-ca-cert" "syslog-tls-cert" "syslog-tls-key" "syslog-tls-skip-verify" "syslog-facility" "tag")
+ syslog_options=("syslog-address" "syslog-format" "syslog-tls-ca-cert" "syslog-tls-cert" "syslog-tls-key" "syslog-tls-skip-verify" "syslog-facility" "tag")
splunk_options=("env" "labels" "splunk-caname" "splunk-capath" "splunk-index" "splunk-insecureskipverify" "splunk-source" "splunk-sourcetype" "splunk-token" "splunk-url" "tag")
[[ $log_driver = (awslogs|all) ]] && _describe -t awslogs-options "awslogs options" awslogs_options "$@" && ret=0
@@ -236,7 +236,15 @@
integer ret=1
if compset -P '*='; then
- _message 'value' && ret=0
+ case "${${words[-1]%=*}#*=}" in
+ (syslog-format)
+ syslog_format_opts=('rfc3164' 'rfc5424')
+ _describe -t syslog-format-opts "Syslog format Options" syslog_format_opts && ret=0
+ ;;
+ *)
+ _message 'value' && ret=0
+ ;;
+ esac
else
__docker_get_log_options -qS "=" && ret=0
fi
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index a152fd0..9a4ab32 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -1092,6 +1092,11 @@
MaxUsage: mem.MaxUsage,
Stats: cgs.MemoryStats.Stats,
Failcnt: mem.Failcnt,
+ Limit: mem.Limit,
+ }
+ // if the container does not set memory limit, use the machineMemory
+ if mem.Limit > daemon.statsCollector.machineMemory && daemon.statsCollector.machineMemory > 0 {
+ s.MemoryStats.Limit = daemon.statsCollector.machineMemory
}
if cgs.PidsStats != nil {
s.PidsStats = types.PidsStats{
diff --git a/daemon/kill.go b/daemon/kill.go
index e6ccfc7..3967f0f 100644
--- a/daemon/kill.go
+++ b/daemon/kill.go
@@ -3,6 +3,7 @@
import (
"fmt"
"runtime"
+ "strings"
"syscall"
"time"
@@ -81,7 +82,14 @@
}
if err := daemon.kill(container, sig); err != nil {
- return fmt.Errorf("Cannot kill container %s: %s", container.ID, err)
+ err = fmt.Errorf("Cannot kill container %s: %s", container.ID, err)
+ // if container or process not exists, ignore the error
+ if strings.Contains(err.Error(), "container not found") ||
+ strings.Contains(err.Error(), "no such process") {
+ logrus.Warnf("%s", err.Error())
+ } else {
+ return err
+ }
}
attributes := map[string]string{
diff --git a/daemon/monitor.go b/daemon/monitor.go
index 0a82c5f..f9f7def 100644
--- a/daemon/monitor.go
+++ b/daemon/monitor.go
@@ -77,6 +77,7 @@
c.Reset(false)
return err
}
+ daemon.LogContainerEvent(c, "start")
case libcontainerd.StatePause:
c.Paused = true
daemon.LogContainerEvent(c, "pause")
diff --git a/daemon/start.go b/daemon/start.go
index 52531f5..1b34f42 100644
--- a/daemon/start.go
+++ b/daemon/start.go
@@ -131,7 +131,6 @@
return err
}
- defer daemon.LogContainerEvent(container, "start") // this is logged even on error
if err := daemon.containerd.Create(container.ID, *spec, libcontainerd.WithRestartManager(container.RestartManager(true))); err != nil {
// if we receive an internal error from the initial start of a container then lets
// return it instead of entering the restart loop
@@ -149,6 +148,9 @@
}
container.Reset(false)
+
+ // start event is logged even on error
+ daemon.LogContainerEvent(container, "start")
return err
}
diff --git a/daemon/stats_collector_unix.go b/daemon/stats_collector_unix.go
index 5010281..fb1931d 100644
--- a/daemon/stats_collector_unix.go
+++ b/daemon/stats_collector_unix.go
@@ -14,6 +14,7 @@
"github.com/Sirupsen/logrus"
"github.com/docker/docker/container"
"github.com/docker/docker/pkg/pubsub"
+ sysinfo "github.com/docker/docker/pkg/system"
"github.com/docker/engine-api/types"
"github.com/opencontainers/runc/libcontainer/system"
)
@@ -35,6 +36,11 @@
clockTicksPerSecond: uint64(system.GetClockTicks()),
bufReader: bufio.NewReaderSize(nil, 128),
}
+ meminfo, err := sysinfo.ReadMemInfo()
+ if err == nil && meminfo.MemTotal > 0 {
+ s.machineMemory = uint64(meminfo.MemTotal)
+ }
+
go s.run()
return s
}
@@ -47,6 +53,7 @@
clockTicksPerSecond uint64
publishers map[*container.Container]*pubsub.Publisher
bufReader *bufio.Reader
+ machineMemory uint64
}
// collect registers the container with the collector and adds it to
diff --git a/docs/extend/plugins_authorization.md b/docs/extend/plugins_authorization.md
index 7db31b8..31a6a07 100644
--- a/docs/extend/plugins_authorization.md
+++ b/docs/extend/plugins_authorization.md
@@ -149,7 +149,7 @@
"User": "The user identification",
"UserAuthNMethod": "The authentication method used",
"RequestMethod": "The HTTP method",
- "RequestUri": "The HTTP request URI",
+ "RequestURI": "The HTTP request URI",
"RequestBody": "Byte array containing the raw HTTP request body",
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string ",
"RequestStatusCode": "Request status code"
@@ -174,7 +174,7 @@
"User": "The user identification",
"UserAuthNMethod": "The authentication method used",
"RequestMethod": "The HTTP method",
- "RequestUri": "The HTTP request URI",
+ "RequestURI": "The HTTP request URI",
"RequestBody": "Byte array containing the raw HTTP request body",
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string",
"RequestStatusCode": "Request status code",
diff --git a/docs/reference/api/docker_remote_api_v1.15.md b/docs/reference/api/docker_remote_api_v1.15.md
index c95a66b..f6a860a 100644
--- a/docs/reference/api/docker_remote_api_v1.15.md
+++ b/docs/reference/api/docker_remote_api_v1.15.md
@@ -151,7 +151,7 @@
"ExposedPorts": {
"22/tcp": {}
},
- "SecurityOpts": [""],
+ "SecurityOpts": [],
"HostConfig": {
"Binds": ["/tmp:/tmp"],
"Links": ["redis3:redis"],
diff --git a/docs/reference/api/docker_remote_api_v1.16.md b/docs/reference/api/docker_remote_api_v1.16.md
index f91f408..630da70 100644
--- a/docs/reference/api/docker_remote_api_v1.16.md
+++ b/docs/reference/api/docker_remote_api_v1.16.md
@@ -151,7 +151,7 @@
"ExposedPorts": {
"22/tcp": {}
},
- "SecurityOpts": [""],
+ "SecurityOpts": [],
"HostConfig": {
"Binds": ["/tmp:/tmp"],
"Links": ["redis3:redis"],
diff --git a/docs/reference/api/docker_remote_api_v1.17.md b/docs/reference/api/docker_remote_api_v1.17.md
index 3da962b..9baa758 100644
--- a/docs/reference/api/docker_remote_api_v1.17.md
+++ b/docs/reference/api/docker_remote_api_v1.17.md
@@ -168,7 +168,7 @@
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
"NetworkMode": "bridge",
"Devices": [],
- "SecurityOpt": [""]
+ "SecurityOpt": []
}
}
diff --git a/docs/reference/api/docker_remote_api_v1.18.md b/docs/reference/api/docker_remote_api_v1.18.md
index 421b169..9de2cc6 100644
--- a/docs/reference/api/docker_remote_api_v1.18.md
+++ b/docs/reference/api/docker_remote_api_v1.18.md
@@ -184,7 +184,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", Config: {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": ""
}
}
diff --git a/docs/reference/api/docker_remote_api_v1.19.md b/docs/reference/api/docker_remote_api_v1.19.md
index 9eeb353..e049dbe 100644
--- a/docs/reference/api/docker_remote_api_v1.19.md
+++ b/docs/reference/api/docker_remote_api_v1.19.md
@@ -191,7 +191,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", "Config": {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": ""
}
}
diff --git a/docs/reference/api/docker_remote_api_v1.20.md b/docs/reference/api/docker_remote_api_v1.20.md
index ac0fc80..dd47ff7 100644
--- a/docs/reference/api/docker_remote_api_v1.20.md
+++ b/docs/reference/api/docker_remote_api_v1.20.md
@@ -156,7 +156,7 @@
},
"Volumes": {
"/volumes/data": {}
- }
+ },
"WorkingDir": "",
"NetworkDisabled": false,
"MacAddress": "12:34:56:78:9a:bc",
@@ -193,7 +193,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", "Config": {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": ""
}
}
diff --git a/docs/reference/api/docker_remote_api_v1.21.md b/docs/reference/api/docker_remote_api_v1.21.md
index 6b3ac2e..7cdfd0f 100644
--- a/docs/reference/api/docker_remote_api_v1.21.md
+++ b/docs/reference/api/docker_remote_api_v1.21.md
@@ -160,7 +160,7 @@
},
"Volumes": {
"/volumes/data": {}
- }
+ },
"WorkingDir": "",
"NetworkDisabled": false,
"MacAddress": "12:34:56:78:9a:bc",
@@ -201,7 +201,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", "Config": {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": "",
"VolumeDriver": ""
}
diff --git a/docs/reference/api/docker_remote_api_v1.22.md b/docs/reference/api/docker_remote_api_v1.22.md
index badd170..d9a860a 100644
--- a/docs/reference/api/docker_remote_api_v1.22.md
+++ b/docs/reference/api/docker_remote_api_v1.22.md
@@ -248,7 +248,7 @@
},
"Volumes": {
"/volumes/data": {}
- }
+ },
"WorkingDir": "",
"NetworkDisabled": false,
"MacAddress": "12:34:56:78:9a:bc",
@@ -294,7 +294,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", "Config": {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": "",
"VolumeDriver": "",
"ShmSize": 67108864
diff --git a/docs/reference/api/docker_remote_api_v1.23.md b/docs/reference/api/docker_remote_api_v1.23.md
index d235e42..eac495f 100644
--- a/docs/reference/api/docker_remote_api_v1.23.md
+++ b/docs/reference/api/docker_remote_api_v1.23.md
@@ -267,7 +267,7 @@
},
"Volumes": {
"/volumes/data": {}
- }
+ },
"WorkingDir": "",
"NetworkDisabled": false,
"MacAddress": "12:34:56:78:9a:bc",
@@ -313,7 +313,7 @@
"Devices": [],
"Ulimits": [{}],
"LogConfig": { "Type": "json-file", "Config": {} },
- "SecurityOpt": [""],
+ "SecurityOpt": [],
"CgroupParent": "",
"VolumeDriver": "",
"ShmSize": 67108864
diff --git a/docs/reference/commandline/images.md b/docs/reference/commandline/images.md
index 8419fd0..9ab9768 100644
--- a/docs/reference/commandline/images.md
+++ b/docs/reference/commandline/images.md
@@ -85,16 +85,16 @@
## Listing the full length image IDs
$ docker images --no-trunc
- REPOSITORY TAG IMAGE ID CREATED SIZE
- <none> <none> 77af4d6b9913e693e8d0b4b294fa62ade6054e6b2f1ffb617ac955dd63fb0182 19 hours ago 1.089 GB
- committest latest b6fa739cedf5ea12a620a439402b6004d057da800f91c7524b5086a5e4749c9f 19 hours ago 1.089 GB
- <none> <none> 78a85c484f71509adeaace20e72e941f6bdd2b25b4c75da8693efd9f61a37921 19 hours ago 1.089 GB
- docker latest 30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago 1.089 GB
- <none> <none> 0124422dd9f9cf7ef15c0617cda3931ee68346455441d66ab8bdc5b05e9fdce5 20 hours ago 1.089 GB
- <none> <none> 18ad6fad340262ac2a636efd98a6d1f0ea775ae3d45240d3418466495a19a81b 22 hours ago 1.082 GB
- <none> <none> f9f1e26352f0a3ba6a0ff68167559f64f3e21ff7ada60366e2d44a04befd1d3a 23 hours ago 1.089 GB
- tryout latest 2629d1fa0b81b222fca63371ca16cbf6a0772d07759ff80e8d1369b926940074 23 hours ago 131.5 MB
- <none> <none> 5ed6274db6ceb2397844896966ea239290555e74ef307030ebb01ff91b1914df 24 hours ago 1.089 GB
+ REPOSITORY TAG IMAGE ID CREATED SIZE
+ <none> <none> sha256:77af4d6b9913e693e8d0b4b294fa62ade6054e6b2f1ffb617ac955dd63fb0182 19 hours ago 1.089 GB
+ committest latest sha256:b6fa739cedf5ea12a620a439402b6004d057da800f91c7524b5086a5e4749c9f 19 hours ago 1.089 GB
+ <none> <none> sha256:78a85c484f71509adeaace20e72e941f6bdd2b25b4c75da8693efd9f61a37921 19 hours ago 1.089 GB
+ docker latest sha256:30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago 1.089 GB
+ <none> <none> sha256:0124422dd9f9cf7ef15c0617cda3931ee68346455441d66ab8bdc5b05e9fdce5 20 hours ago 1.089 GB
+ <none> <none> sha256:18ad6fad340262ac2a636efd98a6d1f0ea775ae3d45240d3418466495a19a81b 22 hours ago 1.082 GB
+ <none> <none> sha256:f9f1e26352f0a3ba6a0ff68167559f64f3e21ff7ada60366e2d44a04befd1d3a 23 hours ago 1.089 GB
+ tryout latest sha256:2629d1fa0b81b222fca63371ca16cbf6a0772d07759ff80e8d1369b926940074 23 hours ago 131.5 MB
+ <none> <none> sha256:5ed6274db6ceb2397844896966ea239290555e74ef307030ebb01ff91b1914df 24 hours ago 1.089 GB
## Listing image digests
diff --git a/docs/reference/run.md b/docs/reference/run.md
index 170dd35..b37dd5a 100644
--- a/docs/reference/run.md
+++ b/docs/reference/run.md
@@ -608,8 +608,8 @@
to the container
--security-opt="no-new-privileges" : Disable container processes from gaining
new privileges
- --security-opt="seccomp:unconfined": Turn off seccomp confinement for the container
- --security-opt="seccomp:profile.json: White listed syscalls seccomp Json file to be used as a seccomp filter
+ --security-opt="seccomp=unconfined": Turn off seccomp confinement for the container
+ --security-opt="seccomp=profile.json: White listed syscalls seccomp Json file to be used as a seccomp filter
You can override the default labeling scheme for each container by specifying
diff --git a/docs/userguide/containers/networkingcontainers.md b/docs/userguide/containers/networkingcontainers.md
index 1ac1364..9355e75 100644
--- a/docs/userguide/containers/networkingcontainers.md
+++ b/docs/userguide/containers/networkingcontainers.md
@@ -35,7 +35,7 @@
$ docker run -d -P --name web training/webapp python app.py
-Use the `docker ps` command to see check the name:
+Use the `docker ps` command to check the name:
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
diff --git a/hack/vendor.sh b/hack/vendor.sh
index 6fe46e5..033e88d 100755
--- a/hack/vendor.sh
+++ b/hack/vendor.sh
@@ -20,7 +20,8 @@
clone git github.com/mistifyio/go-zfs v2.1.1
clone git github.com/tchap/go-patricia v2.1.0
clone git github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
-clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git
+# forked golang.org/x/net package includes a patch for lazy loading trace templates
+clone git golang.org/x/net 78cb2c067747f08b343f20614155233ab4ea2ad3 https://github.com/tonistiigi/net.git
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
clone git github.com/docker/go-connections v0.2.0
@@ -29,7 +30,7 @@
clone git github.com/imdario/mergo 0.2.1
#get libnetwork packages
-clone git github.com/docker/libnetwork v0.7.0-rc.4
+clone git github.com/docker/libnetwork v0.7.0-rc.6
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
diff --git a/integration-cli/docker_api_stats_test.go b/integration-cli/docker_api_stats_test.go
index 10c9fd5..7c3f8d3 100644
--- a/integration-cli/docker_api_stats_test.go
+++ b/integration-cli/docker_api_stats_test.go
@@ -227,3 +227,31 @@
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusNotFound)
}
+
+func (s *DockerSuite) TestApiStatsContainerGetMemoryLimit(c *check.C) {
+ testRequires(c, DaemonIsLinux)
+
+ resp, body, err := sockRequestRaw("GET", "/info", nil, "application/json")
+ c.Assert(err, checker.IsNil)
+ c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
+ var info types.Info
+ err = json.NewDecoder(body).Decode(&info)
+ c.Assert(err, checker.IsNil)
+ body.Close()
+
+ // don't set a memory limit, the memory limit should be system memory
+ conName := "foo"
+ dockerCmd(c, "run", "-d", "--name", conName, "busybox", "top")
+ c.Assert(waitRun(conName), checker.IsNil)
+
+ resp, body, err = sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", conName), nil, "")
+ c.Assert(err, checker.IsNil)
+ c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
+ c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json")
+
+ var v *types.Stats
+ err = json.NewDecoder(body).Decode(&v)
+ c.Assert(err, checker.IsNil)
+ body.Close()
+ c.Assert(fmt.Sprintf("%d", v.MemoryStats.Limit), checker.Equals, fmt.Sprintf("%d", info.MemTotal))
+}
diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go
index f426650..f17b711 100644
--- a/integration-cli/docker_cli_events_test.go
+++ b/integration-cli/docker_cli_events_test.go
@@ -604,3 +604,44 @@
events := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(len(events), checker.GreaterThan, 1, check.Commentf(out))
}
+
+func (s *DockerSuite) TestEventsContainerRestart(c *check.C) {
+ dockerCmd(c, "run", "-d", "--name=testEvent", "--restart=on-failure:3", "busybox", "false")
+
+ // wait until test2 is auto removed.
+ waitTime := 10 * time.Second
+ if daemonPlatform == "windows" {
+ // nslookup isn't present in Windows busybox. Is built-in.
+ waitTime = 90 * time.Second
+ }
+
+ err := waitInspect("testEvent", "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTime)
+ c.Assert(err, checker.IsNil)
+
+ var (
+ createCount int
+ startCount int
+ dieCount int
+ )
+ out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "-f", "container=testEvent")
+ events := strings.Split(strings.TrimSpace(out), "\n")
+
+ nEvents := len(events)
+ c.Assert(nEvents, checker.GreaterOrEqualThan, 1) //Missing expected event
+ actions := eventActionsByIDAndType(c, events, "testEvent", "container")
+
+ for _, a := range actions {
+ switch a {
+ case "create":
+ createCount++
+ case "start":
+ startCount++
+ case "die":
+ dieCount++
+ }
+ }
+ c.Assert(createCount, checker.Equals, 1, check.Commentf("testEvent should be created 1 times: %v", actions))
+ c.Assert(startCount, checker.Equals, 4, check.Commentf("testEvent should start 4 times: %v", actions))
+ c.Assert(dieCount, checker.Equals, 4, check.Commentf("testEvent should die 4 times: %v", actions))
+
+}
diff --git a/integration-cli/docker_cli_restart_test.go b/integration-cli/docker_cli_restart_test.go
index 297e16a..31c8920 100644
--- a/integration-cli/docker_cli_restart_test.go
+++ b/integration-cli/docker_cli_restart_test.go
@@ -188,3 +188,62 @@
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
c.Assert(err, check.IsNil)
}
+
+func (s *DockerSuite) TestRestartPolicyAfterRestart(c *check.C) {
+ testRequires(c, SameHostDaemon)
+
+ out, _ := runSleepingContainer(c, "-d", "--restart=always")
+ id := strings.TrimSpace(out)
+ c.Assert(waitRun(id), check.IsNil)
+
+ dockerCmd(c, "restart", id)
+
+ c.Assert(waitRun(id), check.IsNil)
+
+ pidStr := inspectField(c, id, "State.Pid")
+
+ pid, err := strconv.Atoi(pidStr)
+ c.Assert(err, check.IsNil)
+
+ p, err := os.FindProcess(pid)
+ c.Assert(err, check.IsNil)
+ c.Assert(p, check.NotNil)
+
+ err = p.Kill()
+ c.Assert(err, check.IsNil)
+
+ err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second)
+ c.Assert(err, check.IsNil)
+
+ err = waitInspect(id, "{{.State.Status}}", "running", 30*time.Second)
+ c.Assert(err, check.IsNil)
+}
+
+func (s *DockerSuite) TestRestartContainerwithRestartPolicy(c *check.C) {
+ out1, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "false")
+ out2, _ := dockerCmd(c, "run", "-d", "--restart=always", "busybox", "false")
+
+ id1 := strings.TrimSpace(string(out1))
+ id2 := strings.TrimSpace(string(out2))
+ err := waitInspect(id1, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 30*time.Second)
+ c.Assert(err, checker.IsNil)
+
+ // TODO: fix racey problem during restart:
+ // https://jenkins.dockerproject.org/job/Docker-PRs-Win2Lin/24665/console
+ // Error response from daemon: Cannot restart container 6655f620d90b390527db23c0a15b3e46d86a58ecec20a5697ab228d860174251: remove /var/run/docker/libcontainerd/6655f620d90b390527db23c0a15b3e46d86a58ecec20a5697ab228d860174251/rootfs: device or resource busy
+ if _, _, err := dockerCmdWithError("restart", id1); err != nil {
+ // if restart met racey problem, try again
+ time.Sleep(500 * time.Millisecond)
+ dockerCmd(c, "restart", id1)
+ }
+ if _, _, err := dockerCmdWithError("restart", id2); err != nil {
+ // if restart met racey problem, try again
+ time.Sleep(500 * time.Millisecond)
+ dockerCmd(c, "restart", id2)
+ }
+
+ dockerCmd(c, "stop", id1)
+ dockerCmd(c, "stop", id2)
+ dockerCmd(c, "start", id1)
+ dockerCmd(c, "start", id2)
+}
diff --git a/libcontainerd/client_linux.go b/libcontainerd/client_linux.go
index f747b2f..01806da 100644
--- a/libcontainerd/client_linux.go
+++ b/libcontainerd/client_linux.go
@@ -134,7 +134,7 @@
defer clnt.unlock(containerID)
if ctr, err := clnt.getContainer(containerID); err == nil {
- if ctr.restarting { // docker doesn't actually call start if restart is on atm, but probably should in the future
+ if ctr.restarting {
ctr.restartManager.Cancel()
ctr.clean()
} else {
diff --git a/libcontainerd/container_linux.go b/libcontainerd/container_linux.go
index 506a177..6f168ca 100644
--- a/libcontainerd/container_linux.go
+++ b/libcontainerd/container_linux.go
@@ -121,6 +121,7 @@
} else if restart {
st.State = StateRestart
ctr.restarting = true
+ ctr.client.deleteContainer(e.Id)
go func() {
err := <-wait
ctr.restarting = false
diff --git a/pkg/ioutils/bytespipe.go b/pkg/ioutils/bytespipe.go
index e263c28..fcaecc3 100644
--- a/pkg/ioutils/bytespipe.go
+++ b/pkg/ioutils/bytespipe.go
@@ -49,6 +49,7 @@
bp.mu.Lock()
defer bp.mu.Unlock()
written := 0
+loop0:
for {
if bp.closeErr != nil {
return written, ErrClosed
@@ -75,6 +76,9 @@
// block if too much data is still in the buffer
for bp.bufLen >= blockThreshold {
bp.wait.Wait()
+ if bp.closeErr != nil {
+ continue loop0
+ }
}
// allocate slice that has twice the size of the last unless maximum reached
diff --git a/restartmanager/restartmanager.go b/restartmanager/restartmanager.go
index e534b2c..39b8b15 100644
--- a/restartmanager/restartmanager.go
+++ b/restartmanager/restartmanager.go
@@ -51,7 +51,7 @@
}()
if rm.canceled {
- return false, nil, nil
+ return false, nil, fmt.Errorf("restartmanager canceled")
}
if rm.active {
diff --git a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md
index 0eb85cd..883830f 100644
--- a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md
+++ b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 0.7.0-rc.6 (2016-04-10)
+- Flush cached resolver socket on default gateway change
+
+## 0.7.0-rc.5 (2016-04-08)
+- Persist ipam driver options
+- Fixes https://github.com/docker/libnetwork/issues/1087
+- Use go vet from go tool
+- Godep update to pick up latest docker/docker packages
+- Validate remote driver response using docker plugins package method.
+
## 0.7.0-rc.4 (2016-04-06)
- Fix the handling for default gateway Endpoint join/leave.
diff --git a/vendor/src/github.com/docker/libnetwork/Dockerfile.build b/vendor/src/github.com/docker/libnetwork/Dockerfile.build
index 01b690e..035f852 100644
--- a/vendor/src/github.com/docker/libnetwork/Dockerfile.build
+++ b/vendor/src/github.com/docker/libnetwork/Dockerfile.build
@@ -3,6 +3,5 @@
RUN go get github.com/tools/godep \
github.com/golang/lint/golint \
- golang.org/x/tools/cmd/vet \
golang.org/x/tools/cmd/cover\
github.com/mattn/goveralls
diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go
index 3253353..e3f2cd5 100644
--- a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go
+++ b/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go
@@ -3,7 +3,6 @@
import (
"fmt"
"net"
- "strings"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/plugins"
@@ -14,10 +13,6 @@
"github.com/docker/libnetwork/types"
)
-const (
- missingMethod = "404 page not found"
-)
-
type driver struct {
endpoint *plugins.Client
networkType string
@@ -260,7 +255,7 @@
Options: options,
}
err := d.call("ProgramExternalConnectivity", data, &api.ProgramExternalConnectivityResponse{})
- if err != nil && strings.Contains(err.Error(), missingMethod) {
+ if err != nil && plugins.IsNotFound(err) {
// It is not mandatory yet to support this method
return nil
}
@@ -274,7 +269,7 @@
EndpointID: eid,
}
err := d.call("RevokeExternalConnectivity", data, &api.RevokeExternalConnectivityResponse{})
- if err != nil && strings.Contains(err.Error(), missingMethod) {
+ if err != nil && plugins.IsNotFound(err) {
// It is not mandatory yet to support this method
return nil
}
diff --git a/vendor/src/github.com/docker/libnetwork/endpoint.go b/vendor/src/github.com/docker/libnetwork/endpoint.go
index 55b3a8e..7608dd7 100644
--- a/vendor/src/github.com/docker/libnetwork/endpoint.go
+++ b/vendor/src/github.com/docker/libnetwork/endpoint.go
@@ -477,6 +477,10 @@
ep.Name(), ep.ID(), err)
}
}
+
+ if sb.resolver != nil {
+ sb.resolver.FlushExtServers()
+ }
}
if !sb.needDefaultGW() {
diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go
index ed2b52c..a14550c 100644
--- a/vendor/src/github.com/docker/libnetwork/network.go
+++ b/vendor/src/github.com/docker/libnetwork/network.go
@@ -320,6 +320,13 @@
dstN.labels[k] = v
}
+ if n.ipamOptions != nil {
+ dstN.ipamOptions = make(map[string]string, len(n.ipamOptions))
+ for k, v := range n.ipamOptions {
+ dstN.ipamOptions[k] = v
+ }
+ }
+
for _, v4conf := range n.ipamV4Config {
dstV4Conf := &IpamConf{}
v4conf.CopyTo(dstV4Conf)
@@ -372,6 +379,7 @@
netMap["scope"] = n.scope
netMap["labels"] = n.labels
netMap["ipamType"] = n.ipamType
+ netMap["ipamOptions"] = n.ipamOptions
netMap["addrSpace"] = n.addrSpace
netMap["enableIPv6"] = n.enableIPv6
if n.generic != nil {
@@ -432,6 +440,15 @@
}
}
+ if v, ok := netMap["ipamOptions"]; ok {
+ if iOpts, ok := v.(map[string]interface{}); ok {
+ n.ipamOptions = make(map[string]string, len(iOpts))
+ for k, v := range iOpts {
+ n.ipamOptions[k] = v.(string)
+ }
+ }
+ }
+
if v, ok := netMap["generic"]; ok {
n.generic = v.(map[string]interface{})
// Restore opts in their map[string]string form
diff --git a/vendor/src/github.com/docker/libnetwork/resolver.go b/vendor/src/github.com/docker/libnetwork/resolver.go
index 7af1850..cff692f 100644
--- a/vendor/src/github.com/docker/libnetwork/resolver.go
+++ b/vendor/src/github.com/docker/libnetwork/resolver.go
@@ -45,7 +45,7 @@
ptrIPv6domain = ".ip6.arpa."
respTTL = 600
maxExtDNS = 3 //max number of external servers to try
- extIOTimeout = 3 * time.Second
+ extIOTimeout = 4 * time.Second
defaultRespSize = 512
maxConcurrent = 50
logInterval = 2 * time.Second
@@ -158,6 +158,10 @@
func (r *resolver) FlushExtServers() {
for i := 0; i < maxExtDNS; i++ {
+ if r.extDNSList[i].extConn != nil {
+ r.extDNSList[i].extConn.Close()
+ }
+
r.extDNSList[i].extConn = nil
r.extDNSList[i].extOnce = sync.Once{}
}
@@ -344,9 +348,6 @@
if extDNS.ipStr == "" {
break
}
- log.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,
- w.LocalAddr().String(), proto, extDNS.ipStr)
-
extConnect := func() {
addr := fmt.Sprintf("%s:%d", extDNS.ipStr, 53)
extConn, err = net.DialTimeout(proto, addr, extIOTimeout)
@@ -378,6 +379,8 @@
if extConn == nil {
continue
}
+ log.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,
+ extConn.LocalAddr().String(), proto, extDNS.ipStr)
// Timeout has to be set for every IO operation.
extConn.SetDeadline(time.Now().Add(extIOTimeout))
@@ -424,7 +427,7 @@
break
}
- if resp == nil {
+ if resp == nil || w == nil {
return
}
}
diff --git a/vendor/src/golang.org/x/net/trace/events.go b/vendor/src/golang.org/x/net/trace/events.go
index e66c7e3..d8daec1 100644
--- a/vendor/src/golang.org/x/net/trace/events.go
+++ b/vendor/src/golang.org/x/net/trace/events.go
@@ -21,11 +21,6 @@
"time"
)
-var eventsTmpl = template.Must(template.New("events").Funcs(template.FuncMap{
- "elapsed": elapsed,
- "trimSpace": strings.TrimSpace,
-}).Parse(eventsHTML))
-
const maxEventsPerLog = 100
type bucket struct {
@@ -101,7 +96,7 @@
famMu.RLock()
defer famMu.RUnlock()
- if err := eventsTmpl.Execute(w, data); err != nil {
+ if err := eventsTmpl().Execute(w, data); err != nil {
log.Printf("net/trace: Failed executing template: %v", err)
}
}
@@ -421,6 +416,19 @@
}
}
+var eventsTmplCache *template.Template
+var eventsTmplOnce sync.Once
+
+func eventsTmpl() *template.Template {
+ eventsTmplOnce.Do(func() {
+ eventsTmplCache = template.Must(template.New("events").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "trimSpace": strings.TrimSpace,
+ }).Parse(eventsHTML))
+ })
+ return eventsTmplCache
+}
+
const eventsHTML = `
<html>
<head>
diff --git a/vendor/src/golang.org/x/net/trace/histogram.go b/vendor/src/golang.org/x/net/trace/histogram.go
index bb42aa5..9bf4286 100644
--- a/vendor/src/golang.org/x/net/trace/histogram.go
+++ b/vendor/src/golang.org/x/net/trace/histogram.go
@@ -12,6 +12,7 @@
"html/template"
"log"
"math"
+ "sync"
"golang.org/x/net/internal/timeseries"
)
@@ -320,15 +321,20 @@
func (h *histogram) html() template.HTML {
buf := new(bytes.Buffer)
- if err := distTmpl.Execute(buf, h.newData()); err != nil {
+ if err := distTmpl().Execute(buf, h.newData()); err != nil {
buf.Reset()
log.Printf("net/trace: couldn't execute template: %v", err)
}
return template.HTML(buf.String())
}
-// Input: data
-var distTmpl = template.Must(template.New("distTmpl").Parse(`
+var distTmplCache *template.Template
+var distTmplOnce sync.Once
+
+func distTmpl() *template.Template {
+ distTmplOnce.Do(func() {
+ // Input: data
+ distTmplCache = template.Must(template.New("distTmpl").Parse(`
<table>
<tr>
<td style="padding:0.25em">Count: {{.Count}}</td>
@@ -354,3 +360,6 @@
{{end}}
</table>
`))
+ })
+ return distTmplCache
+}
diff --git a/vendor/src/golang.org/x/net/trace/trace.go b/vendor/src/golang.org/x/net/trace/trace.go
index c44cb7e..0a232a1 100644
--- a/vendor/src/golang.org/x/net/trace/trace.go
+++ b/vendor/src/golang.org/x/net/trace/trace.go
@@ -232,7 +232,7 @@
completedMu.RLock()
defer completedMu.RUnlock()
- if err := pageTmpl.ExecuteTemplate(w, "Page", data); err != nil {
+ if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil {
log.Printf("net/trace: Failed executing template: %v", err)
}
}
@@ -888,10 +888,18 @@
return string(b)
}
-var pageTmpl = template.Must(template.New("Page").Funcs(template.FuncMap{
- "elapsed": elapsed,
- "add": func(a, b int) int { return a + b },
-}).Parse(pageHTML))
+var pageTmplCache *template.Template
+var pageTmplOnce sync.Once
+
+func pageTmpl() *template.Template {
+ pageTmplOnce.Do(func() {
+ pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "add": func(a, b int) int { return a + b },
+ }).Parse(pageHTML))
+ })
+ return pageTmplCache
+}
const pageHTML = `
{{template "Prolog" .}}