Merge pull request #21931 from tiborvass/cherry-picks-1.11.0-rc5
Cherry picks 1.11.0 rc5
This commit is contained in:
commit
642c4a7814
37 changed files with 282 additions and 63 deletions
|
@ -909,6 +909,7 @@ func (container *Container) FullHostname() string {
|
|||
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)
|
||||
|
|
|
@ -216,7 +216,7 @@ __docker_get_log_options() {
|
|||
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 @@ __docker_log_options() {
|
|||
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
|
||||
|
|
|
@ -1092,6 +1092,11 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
|
|||
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{
|
||||
|
|
|
@ -3,6 +3,7 @@ package daemon
|
|||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
@ -81,7 +82,14 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er
|
|||
}
|
||||
|
||||
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{
|
||||
|
|
|
@ -77,6 +77,7 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
|||
c.Reset(false)
|
||||
return err
|
||||
}
|
||||
daemon.LogContainerEvent(c, "start")
|
||||
case libcontainerd.StatePause:
|
||||
c.Paused = true
|
||||
daemon.LogContainerEvent(c, "pause")
|
||||
|
|
|
@ -131,7 +131,6 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
|||
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 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
|||
}
|
||||
|
||||
container.Reset(false)
|
||||
|
||||
// start event is logged even on error
|
||||
daemon.LogContainerEvent(container, "start")
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"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 @@ func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector
|
|||
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 @@ type statsCollector struct {
|
|||
clockTicksPerSecond uint64
|
||||
publishers map[*container.Container]*pubsub.Publisher
|
||||
bufReader *bufio.Reader
|
||||
machineMemory uint64
|
||||
}
|
||||
|
||||
// collect registers the container with the collector and adds it to
|
||||
|
|
|
@ -149,7 +149,7 @@ should implement the following two methods:
|
|||
"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 @@ should implement the following two methods:
|
|||
"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",
|
||||
|
|
|
@ -151,7 +151,7 @@ Create a container
|
|||
"ExposedPorts": {
|
||||
"22/tcp": {}
|
||||
},
|
||||
"SecurityOpts": [""],
|
||||
"SecurityOpts": [],
|
||||
"HostConfig": {
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
|
|
|
@ -151,7 +151,7 @@ Create a container
|
|||
"ExposedPorts": {
|
||||
"22/tcp": {}
|
||||
},
|
||||
"SecurityOpts": [""],
|
||||
"SecurityOpts": [],
|
||||
"HostConfig": {
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
|
|
|
@ -168,7 +168,7 @@ Create a container
|
|||
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
|
||||
"NetworkMode": "bridge",
|
||||
"Devices": [],
|
||||
"SecurityOpt": [""]
|
||||
"SecurityOpt": []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", Config: {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ Create a container
|
|||
},
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
|
@ -193,7 +193,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ Create a container
|
|||
},
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
|
@ -201,7 +201,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": ""
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ Create a container
|
|||
},
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
|
@ -294,7 +294,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": "",
|
||||
"ShmSize": 67108864
|
||||
|
|
|
@ -267,7 +267,7 @@ Create a container
|
|||
},
|
||||
"Volumes": {
|
||||
"/volumes/data": {}
|
||||
}
|
||||
},
|
||||
"WorkingDir": "",
|
||||
"NetworkDisabled": false,
|
||||
"MacAddress": "12:34:56:78:9a:bc",
|
||||
|
@ -313,7 +313,7 @@ Create a container
|
|||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"SecurityOpt": [],
|
||||
"CgroupParent": "",
|
||||
"VolumeDriver": "",
|
||||
"ShmSize": 67108864
|
||||
|
|
|
@ -85,16 +85,16 @@ If nothing matches `REPOSITORY[:TAG]`, the list is empty.
|
|||
## 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
|
||||
|
||||
|
|
|
@ -608,8 +608,8 @@ with the same logic -- if the original volume was specified with a name it will
|
|||
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
|
||||
|
|
|
@ -35,7 +35,7 @@ You name your container by using the `--name` flag, for example launch a new con
|
|||
|
||||
$ 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
|
||||
|
|
|
@ -20,7 +20,8 @@ clone git github.com/mattn/go-sqlite3 v1.1.0
|
|||
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/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
|
|||
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
|
||||
|
|
|
@ -227,3 +227,31 @@ func (s *DockerSuite) TestApiStatsContainerNotFound(c *check.C) {
|
|||
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))
|
||||
}
|
||||
|
|
|
@ -604,3 +604,44 @@ func (s *DockerSuite) TestEventsFilterImageInContainerAction(c *check.C) {
|
|||
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))
|
||||
|
||||
}
|
||||
|
|
|
@ -188,3 +188,62 @@ func (s *DockerSuite) TestRestartWithPolicyUserDefinedNetwork(c *check.C) {
|
|||
_, _, 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)
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
|
|||
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 {
|
||||
|
|
|
@ -121,6 +121,7 @@ func (ctr *container) handleEvent(e *containerd.Event) error {
|
|||
} else if restart {
|
||||
st.State = StateRestart
|
||||
ctr.restarting = true
|
||||
ctr.client.deleteContainer(e.Id)
|
||||
go func() {
|
||||
err := <-wait
|
||||
ctr.restarting = false
|
||||
|
|
|
@ -49,6 +49,7 @@ func (bp *BytesPipe) Write(p []byte) (int, error) {
|
|||
bp.mu.Lock()
|
||||
defer bp.mu.Unlock()
|
||||
written := 0
|
||||
loop0:
|
||||
for {
|
||||
if bp.closeErr != nil {
|
||||
return written, ErrClosed
|
||||
|
@ -75,6 +76,9 @@ func (bp *BytesPipe) Write(p []byte) (int, error) {
|
|||
// 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
|
||||
|
|
|
@ -51,7 +51,7 @@ func (rm *restartManager) ShouldRestart(exitCode uint32) (bool, chan error, erro
|
|||
}()
|
||||
|
||||
if rm.canceled {
|
||||
return false, nil, nil
|
||||
return false, nil, fmt.Errorf("restartmanager canceled")
|
||||
}
|
||||
|
||||
if rm.active {
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -3,6 +3,5 @@ RUN apt-get update && apt-get -y install iptables
|
|||
|
||||
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
|
||||
|
|
|
@ -3,7 +3,6 @@ package remote
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
|
@ -14,10 +13,6 @@ import (
|
|||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
missingMethod = "404 page not found"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
endpoint *plugins.Client
|
||||
networkType string
|
||||
|
@ -260,7 +255,7 @@ func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string
|
|||
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 @@ func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -477,6 +477,10 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
|||
ep.Name(), ep.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if sb.resolver != nil {
|
||||
sb.resolver.FlushExtServers()
|
||||
}
|
||||
}
|
||||
|
||||
if !sb.needDefaultGW() {
|
||||
|
|
|
@ -320,6 +320,13 @@ func (n *network) CopyTo(o datastore.KVObject) error {
|
|||
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 @@ func (n *network) MarshalJSON() ([]byte, error) {
|
|||
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 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -45,7 +45,7 @@ const (
|
|||
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) Start() error {
|
|||
|
||||
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 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
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 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
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 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
break
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
if resp == nil || w == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
20
vendor/src/golang.org/x/net/trace/events.go
vendored
20
vendor/src/golang.org/x/net/trace/events.go
vendored
|
@ -21,11 +21,6 @@ import (
|
|||
"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 @@ func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
|
|||
|
||||
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 @@ func freeEventLog(el *eventLog) {
|
|||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
|
15
vendor/src/golang.org/x/net/trace/histogram.go
vendored
15
vendor/src/golang.org/x/net/trace/histogram.go
vendored
|
@ -12,6 +12,7 @@ import (
|
|||
"html/template"
|
||||
"log"
|
||||
"math"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/internal/timeseries"
|
||||
)
|
||||
|
@ -320,15 +321,20 @@ func (h *histogram) newData() *data {
|
|||
|
||||
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 @@ var distTmpl = template.Must(template.New("distTmpl").Parse(`
|
|||
{{end}}
|
||||
</table>
|
||||
`))
|
||||
})
|
||||
return distTmplCache
|
||||
}
|
||||
|
|
18
vendor/src/golang.org/x/net/trace/trace.go
vendored
18
vendor/src/golang.org/x/net/trace/trace.go
vendored
|
@ -232,7 +232,7 @@ func Render(w io.Writer, req *http.Request, sensitive bool) {
|
|||
|
||||
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 @@ func elapsed(d time.Duration) string {
|
|||
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" .}}
|
||||
|
|
Loading…
Reference in a new issue