From 98b227fecfabb5bc0b1c8bb34392fc093272beee Mon Sep 17 00:00:00 2001 From: Daniel Kerwin Date: Fri, 27 May 2016 12:30:04 +0200 Subject: [PATCH] Add support for shm_size to docker driver. Required update of go-dockerclient to more recent version (ba4298ecf4cfa216f1cce2befbf653359f62c722). --- client/driver/docker.go | 9 + .../fsouza/go-dockerclient/.gitignore | 2 - .../fsouza/go-dockerclient/.travis.yml | 28 --- .../github.com/fsouza/go-dockerclient/AUTHORS | 6 + .../fsouza/go-dockerclient/Makefile | 10 - .../fsouza/go-dockerclient/README.markdown | 3 +- .../github.com/fsouza/go-dockerclient/auth.go | 40 +++- .../fsouza/go-dockerclient/cancelable.go | 17 ++ .../fsouza/go-dockerclient/cancelable_go14.go | 19 ++ .../fsouza/go-dockerclient/client.go | 119 ++++++++--- .../fsouza/go-dockerclient/container.go | 188 +++++++++++++----- .../fsouza/go-dockerclient/event.go | 30 +-- .../fsouza/go-dockerclient/image.go | 92 +++++---- .../fsouza/go-dockerclient/network.go | 7 +- .../fsouza/go-dockerclient/volume.go | 7 +- vendor/vendor.json | 6 +- website/source/docs/drivers/docker.html.md | 2 + 17 files changed, 402 insertions(+), 183 deletions(-) delete mode 100644 vendor/github.com/fsouza/go-dockerclient/.gitignore delete mode 100644 vendor/github.com/fsouza/go-dockerclient/.travis.yml create mode 100644 vendor/github.com/fsouza/go-dockerclient/cancelable.go create mode 100644 vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go diff --git a/client/driver/docker.go b/client/driver/docker.go index b1f29d292..b101dbcbd 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -80,6 +80,7 @@ type DockerDriverConfig struct { SSL bool `mapstructure:"ssl"` // Flag indicating repository is served via https TTY bool `mapstructure:"tty"` // Allocate a Pseudo-TTY Interactive bool `mapstructure:"interactive"` // Keep STDIN open even if not attached + ShmSize int64 `mapstructure:"shm_size"` // Size of /dev/shm of the container in bytes } func (c *DockerDriverConfig) Init() error { @@ -190,6 +191,9 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error { "interactive": &fields.FieldSchema{ Type: fields.TypeBool, }, + "shm_size": &fields.FieldSchema{ + Type: fields.TypeInt, + }, }, } @@ -349,6 +353,11 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, } hostConfig.Privileged = hostPrivileged + // set SHM size + if driverConfig.ShmSize != 0 { + hostConfig.ShmSize = driverConfig.ShmSize + } + // set DNS servers for _, ip := range driverConfig.DNSServers { if net.ParseIP(ip) != nil { diff --git a/vendor/github.com/fsouza/go-dockerclient/.gitignore b/vendor/github.com/fsouza/go-dockerclient/.gitignore deleted file mode 100644 index 5f6b48eae..000000000 --- a/vendor/github.com/fsouza/go-dockerclient/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# temporary symlink for testing -testing/data/symlink diff --git a/vendor/github.com/fsouza/go-dockerclient/.travis.yml b/vendor/github.com/fsouza/go-dockerclient/.travis.yml deleted file mode 100644 index a96df7865..000000000 --- a/vendor/github.com/fsouza/go-dockerclient/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: go -sudo: required -go: - - 1.3.3 - - 1.4.2 - - 1.5.3 - - 1.6 - - tip -env: - - GOARCH=amd64 DOCKER_VERSION=1.7.1 - - GOARCH=386 DOCKER_VERSION=1.7.1 - - GOARCH=amd64 DOCKER_VERSION=1.8.3 - - GOARCH=386 DOCKER_VERSION=1.8.3 - - GOARCH=amd64 DOCKER_VERSION=1.9.1 - - GOARCH=386 DOCKER_VERSION=1.9.1 - - GOARCH=amd64 DOCKER_VERSION=1.10.3 - - GOARCH=386 DOCKER_VERSION=1.10.3 -install: - - travis_retry make prepare_docker -script: - - travis-scripts/run-tests.bash - - DOCKER_HOST=tcp://127.0.0.1:2375 make integration -services: - - docker -matrix: - fast_finish: true - allow_failures: - - go: tip diff --git a/vendor/github.com/fsouza/go-dockerclient/AUTHORS b/vendor/github.com/fsouza/go-dockerclient/AUTHORS index c0913a555..287566e2f 100644 --- a/vendor/github.com/fsouza/go-dockerclient/AUTHORS +++ b/vendor/github.com/fsouza/go-dockerclient/AUTHORS @@ -49,6 +49,7 @@ Fabio Rehm Fatih Arslan Flavia Missi Francisco Souza +Frank Groeneveld George Moura Grégoire Delattre Guillermo Álvarez Fernández @@ -100,12 +101,16 @@ Peter Jihoon Kim Phil Lu Philippe Lafoucrière Rafe Colton +Raphaël Pinson Rob Miller Robert Williamson +Roman Khlystik Salvador Gironès Sam Rijs Sami Wagiaalla +Samuel Archambault Samuel Karp +Seth Jennings Silas Sewell Simon Eskildsen Simon Menke @@ -123,6 +128,7 @@ Tonic ttyh061 Victor Marmol Vincenzo Prignano +Vlad Alexandru Ionescu Wiliam Souza Ye Yin Yu, Zou diff --git a/vendor/github.com/fsouza/go-dockerclient/Makefile b/vendor/github.com/fsouza/go-dockerclient/Makefile index 86b7e0bbb..dd8c73b1b 100644 --- a/vendor/github.com/fsouza/go-dockerclient/Makefile +++ b/vendor/github.com/fsouza/go-dockerclient/Makefile @@ -28,7 +28,6 @@ lint: exit $${status:-0} vet: - @-go get -v golang.org/x/tools/cmd/vet $(foreach pkg,$(PKGS),go vet $(pkg);) fmt: @@ -39,15 +38,6 @@ fmtcheck: [ -n "$${output}" ] && echo "$${output}" && export status=1; \ exit $${status:-0} -prepare_docker: - sudo stop docker || true - sudo rm -rf /var/lib/docker - sudo rm -f `which docker` - sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D - echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | sudo tee /etc/apt/sources.list.d/docker.list - sudo apt-get update - sudo apt-get install docker-engine=$(DOCKER_VERSION)-0~$(shell lsb_release -cs) -y --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" - pretest: lint vet fmtcheck gotest: diff --git a/vendor/github.com/fsouza/go-dockerclient/README.markdown b/vendor/github.com/fsouza/go-dockerclient/README.markdown index b915039f1..234b9e49e 100644 --- a/vendor/github.com/fsouza/go-dockerclient/README.markdown +++ b/vendor/github.com/fsouza/go-dockerclient/README.markdown @@ -1,10 +1,11 @@ # go-dockerclient -[![Travis](https://img.shields.io/travis/fsouza/go-dockerclient.svg?style=flat-square)](https://travis-ci.org/fsouza/go-dockerclient) +[![Travis](https://img.shields.io/travis/fsouza/go-dockerclient/master.svg?style=flat-square)](https://travis-ci.org/fsouza/go-dockerclient) [![GoDoc](https://img.shields.io/badge/api-Godoc-blue.svg?style=flat-square)](https://godoc.org/github.com/fsouza/go-dockerclient) This package presents a client for the Docker remote API. It also provides support for the extensions in the [Swarm API](https://docs.docker.com/swarm/swarm-api/). +It currently supports the Docker API up to version 1.23. This package also provides support for docker's network API, which is a simple passthrough to the libnetwork remote API. Note that docker's network API is diff --git a/vendor/github.com/fsouza/go-dockerclient/auth.go b/vendor/github.com/fsouza/go-dockerclient/auth.go index 775c70c0b..95596d782 100644 --- a/vendor/github.com/fsouza/go-dockerclient/auth.go +++ b/vendor/github.com/fsouza/go-dockerclient/auth.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "os" "path" "strings" @@ -82,10 +83,12 @@ func parseDockerConfig(r io.Reader) (map[string]dockerConfig, error) { buf.ReadFrom(r) byteData := buf.Bytes() - var confsWrapper map[string]map[string]dockerConfig + confsWrapper := struct { + Auths map[string]dockerConfig `json:"auths"` + }{} if err := json.Unmarshal(byteData, &confsWrapper); err == nil { - if confs, ok := confsWrapper["auths"]; ok { - return confs, nil + if len(confsWrapper.Auths) > 0 { + return confsWrapper.Auths, nil } } @@ -120,17 +123,36 @@ func authConfigs(confs map[string]dockerConfig) (*AuthConfigurations, error) { return c, nil } +// AuthStatus returns the authentication status for Docker API versions >= 1.23. +type AuthStatus struct { + Status string `json:"Status,omitempty" yaml:"Status,omitempty"` + IdentityToken string `json:"IdentityToken,omitempty" yaml:"IdentityToken,omitempty"` +} + // AuthCheck validates the given credentials. It returns nil if successful. // -// See https://goo.gl/m2SleN for more details. -func (c *Client) AuthCheck(conf *AuthConfiguration) error { +// For Docker API versions >= 1.23, the AuthStatus struct will be populated, otherwise it will be empty.` +// +// See https://goo.gl/6nsZkH for more details. +func (c *Client) AuthCheck(conf *AuthConfiguration) (AuthStatus, error) { + var authStatus AuthStatus if conf == nil { - return fmt.Errorf("conf is nil") + return authStatus, fmt.Errorf("conf is nil") } resp, err := c.do("POST", "/auth", doOptions{data: conf}) if err != nil { - return err + return authStatus, err } - resp.Body.Close() - return nil + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return authStatus, err + } + if len(data) == 0 { + return authStatus, nil + } + if err := json.Unmarshal(data, &authStatus); err != nil { + return authStatus, err + } + return authStatus, nil } diff --git a/vendor/github.com/fsouza/go-dockerclient/cancelable.go b/vendor/github.com/fsouza/go-dockerclient/cancelable.go new file mode 100644 index 000000000..375fbd15c --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/cancelable.go @@ -0,0 +1,17 @@ +// Copyright 2016 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.5 + +package docker + +import "net/http" + +func cancelable(client *http.Client, req *http.Request) func() { + ch := make(chan struct{}) + req.Cancel = ch + return func() { + close(ch) + } +} diff --git a/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go b/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go new file mode 100644 index 000000000..3c203986f --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go @@ -0,0 +1,19 @@ +// Copyright 2016 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.5 + +package docker + +import "net/http" + +func cancelable(client *http.Client, req *http.Request) func() { + return func() { + if rc, ok := client.Transport.(interface { + CancelRequest(*http.Request) + }); ok { + rc.CancelRequest(req) + } + } +} diff --git a/vendor/github.com/fsouza/go-dockerclient/client.go b/vendor/github.com/fsouza/go-dockerclient/client.go index d893ba684..a3f09cd8b 100644 --- a/vendor/github.com/fsouza/go-dockerclient/client.go +++ b/vendor/github.com/fsouza/go-dockerclient/client.go @@ -27,6 +27,7 @@ import ( "runtime" "strconv" "strings" + "sync/atomic" "time" "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/opts" @@ -44,6 +45,9 @@ var ( // ErrConnectionRefused is returned when the client cannot connect to the given endpoint. ErrConnectionRefused = errors.New("cannot connect to Docker endpoint") + // ErrInactivityTimeout is returned when a streamable call has been inactive for some time. + ErrInactivityTimeout = errors.New("inactivity time exceeded timeout") + apiVersion112, _ = NewAPIVersion("1.12") apiVersion119, _ = NewAPIVersion("1.19") @@ -436,8 +440,11 @@ type streamOptions struct { in io.Reader stdout io.Writer stderr io.Writer - // timeout is the inital connection timeout + // timeout is the initial connection timeout timeout time.Duration + // Timeout with no data is received, it's reset every time new data + // arrives + inactivityTimeout time.Duration } func (c *Client) stream(method, path string, streamOptions streamOptions) error { @@ -470,11 +477,13 @@ func (c *Client) stream(method, path string, streamOptions streamOptions) error if streamOptions.stderr == nil { streamOptions.stderr = ioutil.Discard } + cancelRequest := cancelable(c.HTTPClient, req) if protocol == "unix" { dial, err := c.Dialer.Dial(protocol, address) if err != nil { return err } + cancelRequest = func() { dial.Close() } defer dial.Close() breader := bufio.NewReader(dial) err = req.Write(dial) @@ -509,33 +518,24 @@ func (c *Client) stream(method, path string, streamOptions streamOptions) error if resp.StatusCode < 200 || resp.StatusCode >= 400 { return newError(resp) } - if streamOptions.useJSONDecoder || resp.Header.Get("Content-Type") == "application/json" { - // if we want to get raw json stream, just copy it back to output - // without decoding it - if streamOptions.rawJSONStream { - _, err = io.Copy(streamOptions.stdout, resp.Body) - return err + var canceled uint32 + if streamOptions.inactivityTimeout > 0 { + ch := handleInactivityTimeout(&streamOptions, cancelRequest, &canceled) + defer close(ch) + } + err = handleStreamResponse(resp, &streamOptions) + if err != nil { + if atomic.LoadUint32(&canceled) != 0 { + return ErrInactivityTimeout } - dec := json.NewDecoder(resp.Body) - for { - var m jsonMessage - if err := dec.Decode(&m); err == io.EOF { - break - } else if err != nil { - return err - } - if m.Stream != "" { - fmt.Fprint(streamOptions.stdout, m.Stream) - } else if m.Progress != "" { - fmt.Fprintf(streamOptions.stdout, "%s %s\r", m.Status, m.Progress) - } else if m.Error != "" { - return errors.New(m.Error) - } - if m.Status != "" { - fmt.Fprintln(streamOptions.stdout, m.Status) - } - } - } else { + return err + } + return nil +} + +func handleStreamResponse(resp *http.Response, streamOptions *streamOptions) error { + var err error + if !streamOptions.useJSONDecoder && resp.Header.Get("Content-Type") != "application/json" { if streamOptions.setRawTerminal { _, err = io.Copy(streamOptions.stdout, resp.Body) } else { @@ -543,9 +543,74 @@ func (c *Client) stream(method, path string, streamOptions streamOptions) error } return err } + // if we want to get raw json stream, just copy it back to output + // without decoding it + if streamOptions.rawJSONStream { + _, err = io.Copy(streamOptions.stdout, resp.Body) + return err + } + dec := json.NewDecoder(resp.Body) + for { + var m jsonMessage + if err := dec.Decode(&m); err == io.EOF { + break + } else if err != nil { + return err + } + if m.Stream != "" { + fmt.Fprint(streamOptions.stdout, m.Stream) + } else if m.Progress != "" { + fmt.Fprintf(streamOptions.stdout, "%s %s\r", m.Status, m.Progress) + } else if m.Error != "" { + return errors.New(m.Error) + } + if m.Status != "" { + fmt.Fprintln(streamOptions.stdout, m.Status) + } + } return nil } +type proxyWriter struct { + io.Writer + calls uint64 +} + +func (p *proxyWriter) callCount() uint64 { + return atomic.LoadUint64(&p.calls) +} + +func (p *proxyWriter) Write(data []byte) (int, error) { + atomic.AddUint64(&p.calls, 1) + return p.Writer.Write(data) +} + +func handleInactivityTimeout(options *streamOptions, cancelRequest func(), canceled *uint32) chan<- struct{} { + done := make(chan struct{}) + proxyStdout := &proxyWriter{Writer: options.stdout} + proxyStderr := &proxyWriter{Writer: options.stderr} + options.stdout = proxyStdout + options.stderr = proxyStderr + go func() { + var lastCallCount uint64 + for { + select { + case <-time.After(options.inactivityTimeout): + case <-done: + return + } + curCallCount := proxyStdout.callCount() + proxyStderr.callCount() + if curCallCount == lastCallCount { + atomic.AddUint32(canceled, 1) + cancelRequest() + return + } + lastCallCount = curCallCount + } + }() + return done +} + type hijackOptions struct { success chan struct{} setRawTerminal bool diff --git a/vendor/github.com/fsouza/go-dockerclient/container.go b/vendor/github.com/fsouza/go-dockerclient/container.go index c75318895..f7ed5f574 100644 --- a/vendor/github.com/fsouza/go-dockerclient/container.go +++ b/vendor/github.com/fsouza/go-dockerclient/container.go @@ -14,6 +14,8 @@ import ( "strconv" "strings" "time" + + "github.com/fsouza/go-dockerclient/external/github.com/docker/go-units" ) // ErrContainerAlreadyExists is the error returned by CreateContainer when the @@ -40,6 +42,17 @@ type APIPort struct { IP string `json:"IP,omitempty" yaml:"IP,omitempty"` } +// APIMount represents a mount point for a container. +type APIMount struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty"` + Source string `json:"Source,omitempty" yaml:"Source,omitempty"` + Destination string `json:"Destination,omitempty" yaml:"Destination,omitempty"` + Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"` + Mode string `json:"Mode,omitempty" yaml:"Mode,omitempty"` + RW bool `json:"RW,omitempty" yaml:"RW,omitempty"` + Propogation string `json:"Propogation,omitempty" yaml:"Propogation,omitempty"` +} + // APIContainers represents each container in the list returned by // ListContainers. type APIContainers struct { @@ -47,6 +60,7 @@ type APIContainers struct { Image string `json:"Image,omitempty" yaml:"Image,omitempty"` Command string `json:"Command,omitempty" yaml:"Command,omitempty"` Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"` + State string `json:"State,omitempty" yaml:"State,omitempty"` Status string `json:"Status,omitempty" yaml:"Status,omitempty"` Ports []APIPort `json:"Ports,omitempty" yaml:"Ports,omitempty"` SizeRw int64 `json:"SizeRw,omitempty" yaml:"SizeRw,omitempty"` @@ -54,6 +68,7 @@ type APIContainers struct { Names []string `json:"Names,omitempty" yaml:"Names,omitempty"` Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"` Networks NetworkList `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"` + Mounts []APIMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"` } // NetworkList encapsulates a map of networks, as returned by the Docker API in @@ -99,26 +114,73 @@ func (p Port) Proto() string { // State represents the state of a container. type State struct { - Running bool `json:"Running,omitempty" yaml:"Running,omitempty"` - Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"` - Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"` - OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"` - Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"` - ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"` - Error string `json:"Error,omitempty" yaml:"Error,omitempty"` - StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"` - FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"` + Status string `json:"Status,omitempty" yaml:"Status,omitempty"` + Running bool `json:"Running,omitempty" yaml:"Running,omitempty"` + Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"` + Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"` + OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"` + RemovalInProgress bool `json:"RemovalInProgress,omitempty" yaml:"RemovalInProgress,omitempty"` + Dead bool `json:"Dead,omitempty" yaml:"Dead,omitempty"` + Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"` + ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"` + Error string `json:"Error,omitempty" yaml:"Error,omitempty"` + StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"` + FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"` } -// String returns the string representation of a state. +// String returns a human-readable description of the state func (s *State) String() string { + if s.Running { + if s.Paused { + return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) + } + if s.Restarting { + return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) + } + + return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt))) + } + + if s.RemovalInProgress { + return "Removal In Progress" + } + + if s.Dead { + return "Dead" + } + + if s.StartedAt.IsZero() { + return "Created" + } + + if s.FinishedAt.IsZero() { + return "" + } + + return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) +} + +// StateString returns a single string to describe state +func (s *State) StateString() string { if s.Running { if s.Paused { return "paused" } - return fmt.Sprintf("Up %s", time.Now().UTC().Sub(s.StartedAt)) + if s.Restarting { + return "restarting" + } + return "running" } - return fmt.Sprintf("Exit %d", s.ExitCode) + + if s.Dead { + return "dead" + } + + if s.StartedAt.IsZero() { + return "created" + } + + return "exited" } // PortBinding represents the host/container port mapping as returned in the @@ -213,6 +275,7 @@ type Config struct { MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"` MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty"` KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty"` + PidsLimit int64 `json:"PidsLimit,omitempty" yaml:"PidsLimit,omitempty"` CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"` CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"` AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"` @@ -279,6 +342,12 @@ type SwarmNode struct { Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"` } +// GraphDriver contains information about the GraphDriver used by the container +type GraphDriver struct { + Name string `json:"Name,omitempty" yaml:"Name,omitempty"` + Data map[string]string `json:"Data,omitempty" yaml:"Data,omitempty"` +} + // Container is the type encompasing everything about a container - its config, // hostconfig, etc. type Container struct { @@ -306,10 +375,11 @@ type Container struct { Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"` Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"` - Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty"` - VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty"` - HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"` - ExecIDs []string `json:"ExecIDs,omitempty" yaml:"ExecIDs,omitempty"` + Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty"` + VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty"` + HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"` + ExecIDs []string `json:"ExecIDs,omitempty" yaml:"ExecIDs,omitempty"` + GraphDriver *GraphDriver `json:"GraphDriver,omitempty" yaml:"GraphDriver,omitempty"` RestartCount int `json:"RestartCount,omitempty" yaml:"RestartCount,omitempty"` @@ -320,16 +390,17 @@ type Container struct { // // See https://goo.gl/Y6fXUy for more details. type UpdateContainerOptions struct { - BlkioWeight int `json:"BlkioWeight"` - CPUShares int `json:"CpuShares"` - CPUPeriod int `json:"CpuPeriod"` - CPUQuota int `json:"CpuQuota"` - CpusetCpus string `json:"CpusetCpus"` - CpusetMems string `json:"CpusetMems"` - Memory int `json:"Memory"` - MemorySwap int `json:"MemorySwap"` - MemoryReservation int `json:"MemoryReservation"` - KernelMemory int `json:"KernelMemory"` + BlkioWeight int `json:"BlkioWeight"` + CPUShares int `json:"CpuShares"` + CPUPeriod int `json:"CpuPeriod"` + CPUQuota int `json:"CpuQuota"` + CpusetCpus string `json:"CpusetCpus"` + CpusetMems string `json:"CpusetMems"` + Memory int `json:"Memory"` + MemorySwap int `json:"MemorySwap"` + MemoryReservation int `json:"MemoryReservation"` + KernelMemory int `json:"KernelMemory"` + RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty"` } // UpdateContainer updates the container at ID with the options @@ -541,6 +612,7 @@ type HostConfig struct { DNSSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"` ExtraHosts []string `json:"ExtraHosts,omitempty" yaml:"ExtraHosts,omitempty"` VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"` + UsernsMode string `json:"UsernsMode,omitempty" yaml:"UsernsMode,omitempty"` NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"` IpcMode string `json:"IpcMode,omitempty" yaml:"IpcMode,omitempty"` PidMode string `json:"PidMode,omitempty" yaml:"PidMode,omitempty"` @@ -570,6 +642,7 @@ type HostConfig struct { Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty"` VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"` OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty"` + ShmSize int64 `json:"ShmSize,omitempty" yaml:"ShmSize,omitempty"` } // StartContainer starts a container, returning an error in case of failure. @@ -697,7 +770,10 @@ func (c *Client) TopContainer(id string, psArgs string) (TopResult, error) { // // See https://goo.gl/GNmLHb for more details. type Stats struct { - Read time.Time `json:"read,omitempty" yaml:"read,omitempty"` + Read time.Time `json:"read,omitempty" yaml:"read,omitempty"` + PidsStats struct { + Current uint64 `json:"current,omitempty" yaml:"current,omitempty"` + } `json:"pids_stats,omitempty" yaml:"pids_stats,omitempty"` Network NetworkStats `json:"network,omitempty" yaml:"network,omitempty"` Networks map[string]NetworkStats `json:"networks,omitempty" yaml:"networks,omitempty"` MemoryStats struct { @@ -800,6 +876,9 @@ type StatsOptions struct { Done <-chan bool // Initial connection timeout Timeout time.Duration + // Timeout with no data is received, it's reset every time new data + // arrives + InactivityTimeout time.Duration `qs:"-"` } // Stats sends container statistics for the given container to the given channel. @@ -834,10 +913,11 @@ func (c *Client) Stats(opts StatsOptions) (retErr error) { go func() { err := c.stream("GET", fmt.Sprintf("/containers/%s/stats?stream=%v", opts.ID, opts.Stream), streamOptions{ - rawJSONStream: true, - useJSONDecoder: true, - stdout: writeCloser, - timeout: opts.Timeout, + rawJSONStream: true, + useJSONDecoder: true, + stdout: writeCloser, + timeout: opts.Timeout, + inactivityTimeout: opts.InactivityTimeout, }) if err != nil { dockerError, ok := err.(*Error) @@ -967,8 +1047,9 @@ func (c *Client) UploadToContainer(id string, opts UploadToContainerOptions) err // // See https://goo.gl/KnZJDX for more details. type DownloadFromContainerOptions struct { - OutputStream io.Writer `json:"-" qs:"-"` - Path string `qs:"path"` + OutputStream io.Writer `json:"-" qs:"-"` + Path string `qs:"path"` + InactivityTimeout time.Duration `qs:"-"` } // DownloadFromContainer downloads a tar archive of files or folders in a container. @@ -978,8 +1059,9 @@ func (c *Client) DownloadFromContainer(id string, opts DownloadFromContainerOpti url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts) return c.stream("GET", url, streamOptions{ - setRawTerminal: true, - stdout: opts.OutputStream, + setRawTerminal: true, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -1134,15 +1216,16 @@ func (c *Client) AttachToContainerNonBlocking(opts AttachToContainerOptions) (Cl // // See https://goo.gl/yl8PGm for more details. type LogsOptions struct { - Container string `qs:"-"` - OutputStream io.Writer `qs:"-"` - ErrorStream io.Writer `qs:"-"` - Follow bool - Stdout bool - Stderr bool - Since int64 - Timestamps bool - Tail string + Container string `qs:"-"` + OutputStream io.Writer `qs:"-"` + ErrorStream io.Writer `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` + Follow bool + Stdout bool + Stderr bool + Since int64 + Timestamps bool + Tail string // Use raw terminal? Usually true when the container contains a TTY. RawTerminal bool `qs:"-"` @@ -1160,9 +1243,10 @@ func (c *Client) Logs(opts LogsOptions) error { } path := "/containers/" + opts.Container + "/logs?" + queryString(opts) return c.stream("GET", path, streamOptions{ - setRawTerminal: opts.RawTerminal, - stdout: opts.OutputStream, - stderr: opts.ErrorStream, + setRawTerminal: opts.RawTerminal, + stdout: opts.OutputStream, + stderr: opts.ErrorStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -1186,8 +1270,9 @@ func (c *Client) ResizeContainerTTY(id string, height, width int) error { // // See https://goo.gl/dOkTyk for more details. type ExportContainerOptions struct { - ID string - OutputStream io.Writer + ID string + OutputStream io.Writer + InactivityTimeout time.Duration `qs:"-"` } // ExportContainer export the contents of container id as tar archive @@ -1200,8 +1285,9 @@ func (c *Client) ExportContainer(opts ExportContainerOptions) error { } url := fmt.Sprintf("/containers/%s/export", opts.ID) return c.stream("GET", url, streamOptions{ - setRawTerminal: true, - stdout: opts.OutputStream, + setRawTerminal: true, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } diff --git a/vendor/github.com/fsouza/go-dockerclient/event.go b/vendor/github.com/fsouza/go-dockerclient/event.go index 6634e9231..83b5cf52d 100644 --- a/vendor/github.com/fsouza/go-dockerclient/event.go +++ b/vendor/github.com/fsouza/go-dockerclient/event.go @@ -334,8 +334,8 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan // transformEvent takes an event and determines what version it is from // then populates both versions of the event func transformEvent(event *APIEvents) { - // if <= 1.21, `status` and `ID` will be populated - if event.Status != "" && event.ID != "" { + // if event version is <= 1.21 there will be no Action and no Type + if event.Action == "" && event.Type == "" { event.Action = event.Status event.Actor.ID = event.ID event.Actor.Attributes = map[string]string{} @@ -349,16 +349,22 @@ func transformEvent(event *APIEvents) { } } } else { - if event.Type == "image" || event.Type == "container" { - event.Status = event.Action - } else { - // Because just the Status has been overloaded with different Types - // if an event is not for an image or a container, we prepend the type - // to avoid problems for people relying on actions being only for - // images and containers - event.Status = event.Type + ":" + event.Action + if event.Status == "" { + if event.Type == "image" || event.Type == "container" { + event.Status = event.Action + } else { + // Because just the Status has been overloaded with different Types + // if an event is not for an image or a container, we prepend the type + // to avoid problems for people relying on actions being only for + // images and containers + event.Status = event.Type + ":" + event.Action + } + } + if event.ID == "" { + event.ID = event.Actor.ID + } + if event.From == "" { + event.From = event.Actor.Attributes["image"] } - event.ID = event.Actor.ID - event.From = event.Actor.Attributes["image"] } } diff --git a/vendor/github.com/fsouza/go-dockerclient/image.go b/vendor/github.com/fsouza/go-dockerclient/image.go index f65665a4c..fd51c3f92 100644 --- a/vendor/github.com/fsouza/go-dockerclient/image.go +++ b/vendor/github.com/fsouza/go-dockerclient/image.go @@ -29,9 +29,16 @@ type APIImages struct { Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"` } +// RootFS represents the underlying layers used by an image +type RootFS struct { + Type string `json:"Type,omitempty" yaml:"Type,omitempty"` + Layers []string `json:"Layers,omitempty" yaml:"Layers,omitempty"` +} + // Image is the type representing a docker image and its various properties type Image struct { ID string `json:"Id" yaml:"Id"` + RepoTags []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"` Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"` Comment string `json:"Comment,omitempty" yaml:"Comment,omitempty"` Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"` @@ -44,6 +51,7 @@ type Image struct { Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"` VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"` RepoDigests []string `json:"RepoDigests,omitempty" yaml:"RepoDigests,omitempty"` + RootFS *RootFS `json:"RootFS,omitempty" yaml:"RootFS,omitempty"` } // ImagePre012 serves the same purpose as the Image type except that it is for @@ -235,8 +243,9 @@ type PushImageOptions struct { // Registry server to push the image Registry string - OutputStream io.Writer `qs:"-"` - RawJSONStream bool `qs:"-"` + OutputStream io.Writer `qs:"-"` + RawJSONStream bool `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` } // PushImage pushes an image to a remote registry, logging progress to w. @@ -257,10 +266,11 @@ func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error opts.Name = "" path := "/images/" + name + "/push?" + queryString(&opts) return c.stream("POST", path, streamOptions{ - setRawTerminal: true, - rawJSONStream: opts.RawJSONStream, - headers: headers, - stdout: opts.OutputStream, + setRawTerminal: true, + rawJSONStream: opts.RawJSONStream, + headers: headers, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -269,11 +279,13 @@ func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error // // See https://goo.gl/iJkZjD for more details. type PullImageOptions struct { - Repository string `qs:"fromImage"` - Registry string - Tag string - OutputStream io.Writer `qs:"-"` - RawJSONStream bool `qs:"-"` + Repository string `qs:"fromImage"` + Registry string + Tag string + + OutputStream io.Writer `qs:"-"` + RawJSONStream bool `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` } // PullImage pulls an image from a remote registry, logging progress to @@ -289,17 +301,18 @@ func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error if err != nil { return err } - return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream) + return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream, opts.InactivityTimeout) } -func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error { +func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool, timeout time.Duration) error { path := "/images/create?" + qs return c.stream("POST", path, streamOptions{ - setRawTerminal: true, - rawJSONStream: rawJSONStream, - headers: headers, - in: in, - stdout: w, + setRawTerminal: true, + headers: headers, + in: in, + stdout: w, + rawJSONStream: rawJSONStream, + inactivityTimeout: timeout, }) } @@ -324,8 +337,9 @@ func (c *Client) LoadImage(opts LoadImageOptions) error { // // See https://goo.gl/le7vK8 for more details. type ExportImageOptions struct { - Name string - OutputStream io.Writer + Name string + OutputStream io.Writer + InactivityTimeout time.Duration `qs:"-"` } // ExportImage exports an image (as a tar file) into the stream. @@ -333,8 +347,9 @@ type ExportImageOptions struct { // See https://goo.gl/le7vK8 for more details. func (c *Client) ExportImage(opts ExportImageOptions) error { return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.Name), streamOptions{ - setRawTerminal: true, - stdout: opts.OutputStream, + setRawTerminal: true, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -342,8 +357,9 @@ func (c *Client) ExportImage(opts ExportImageOptions) error { // // See https://goo.gl/huC7HA for more details. type ExportImagesOptions struct { - Names []string - OutputStream io.Writer `qs:"-"` + Names []string + OutputStream io.Writer `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` } // ExportImages exports one or more images (as a tar file) into the stream @@ -354,8 +370,9 @@ func (c *Client) ExportImages(opts ExportImagesOptions) error { return ErrMustSpecifyNames } return c.stream("GET", "/images/get?"+queryString(&opts), streamOptions{ - setRawTerminal: true, - stdout: opts.OutputStream, + setRawTerminal: true, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -368,9 +385,10 @@ type ImportImageOptions struct { Source string `qs:"fromSrc"` Tag string `qs:"tag"` - InputStream io.Reader `qs:"-"` - OutputStream io.Writer `qs:"-"` - RawJSONStream bool `qs:"-"` + InputStream io.Reader `qs:"-"` + OutputStream io.Writer `qs:"-"` + RawJSONStream bool `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` } // ImportImage imports an image from a url, a file or stdin @@ -391,7 +409,7 @@ func (c *Client) ImportImage(opts ImportImageOptions) error { opts.InputStream = f opts.Source = "-" } - return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, opts.RawJSONStream) + return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, opts.RawJSONStream, opts.InactivityTimeout) } // BuildImageOptions present the set of informations available for building an @@ -422,6 +440,7 @@ type BuildImageOptions struct { ContextDir string `qs:"-"` Ulimits []ULimit `qs:"-"` BuildArgs []BuildArg `qs:"-"` + InactivityTimeout time.Duration `qs:"-"` } // BuildArg represents arguments that can be passed to the image when building @@ -487,11 +506,12 @@ func (c *Client) BuildImage(opts BuildImageOptions) error { } return c.stream("POST", fmt.Sprintf("/build?%s", qs), streamOptions{ - setRawTerminal: true, - rawJSONStream: opts.RawJSONStream, - headers: headers, - in: opts.InputStream, - stdout: opts.OutputStream, + setRawTerminal: true, + rawJSONStream: opts.RawJSONStream, + headers: headers, + in: opts.InputStream, + stdout: opts.OutputStream, + inactivityTimeout: opts.InactivityTimeout, }) } @@ -584,10 +604,10 @@ type APIImageSearch struct { // See https://goo.gl/AYjyrF for more details. func (c *Client) SearchImages(term string) ([]APIImageSearch, error) { resp, err := c.do("GET", "/images/search?term="+term, doOptions{}) - defer resp.Body.Close() if err != nil { return nil, err } + defer resp.Body.Close() var searchResult []APIImageSearch if err := json.NewDecoder(resp.Body).Decode(&searchResult); err != nil { return nil, err diff --git a/vendor/github.com/fsouza/go-dockerclient/network.go b/vendor/github.com/fsouza/go-dockerclient/network.go index b72e91a07..a6812495b 100644 --- a/vendor/github.com/fsouza/go-dockerclient/network.go +++ b/vendor/github.com/fsouza/go-dockerclient/network.go @@ -28,6 +28,7 @@ type Network struct { Containers map[string]Endpoint Options map[string]string Internal bool + EnableIPv6 bool `json:"EnableIPv6"` } // Endpoint contains network resources allocated and used for a container in a network @@ -111,7 +112,9 @@ type CreateNetworkOptions struct { CheckDuplicate bool `json:"CheckDuplicate"` Driver string `json:"Driver"` IPAM IPAMOptions `json:"IPAM"` - Options map[string]interface{} `json:"options"` + Options map[string]interface{} `json:"Options"` + Internal bool `json:"Internal"` + EnableIPv6 bool `json:"EnableIPv6"` } // IPAMOptions controls IP Address Management when creating a network @@ -119,7 +122,7 @@ type CreateNetworkOptions struct { // See https://goo.gl/T8kRVH for more details. type IPAMOptions struct { Driver string `json:"Driver"` - Config []IPAMConfig `json:"IPAMConfig"` + Config []IPAMConfig `json:"Config"` } // IPAMConfig represents IPAM configurations diff --git a/vendor/github.com/fsouza/go-dockerclient/volume.go b/vendor/github.com/fsouza/go-dockerclient/volume.go index 0e57cb122..5fe8ee3d6 100644 --- a/vendor/github.com/fsouza/go-dockerclient/volume.go +++ b/vendor/github.com/fsouza/go-dockerclient/volume.go @@ -22,9 +22,10 @@ var ( // // See https://goo.gl/FZA4BK for more details. type Volume struct { - Name string `json:"Name" yaml:"Name"` - Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"` - Mountpoint string `json:"Mountpoint,omitempty" yaml:"Mountpoint,omitempty"` + Name string `json:"Name" yaml:"Name"` + Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"` + Mountpoint string `json:"Mountpoint,omitempty" yaml:"Mountpoint,omitempty"` + Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"` } // ListVolumesOptions specify parameters to the ListVolumes function. diff --git a/vendor/vendor.json b/vendor/vendor.json index a6d885eb4..32e59a998 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -175,8 +175,10 @@ "revision": "8929fe90cee4b2cb9deb468b51fb34eba64d1bf0" }, { + "checksumSHA1": "bA5kwt3jUUgTELOvV6yRg4fwn8c=", "path": "github.com/fsouza/go-dockerclient", - "revision": "7c07ffce0f7e14a4da49ce92a2842d4e87be1c1e" + "revision": "ba4298ecf4cfa216f1cce2befbf653359f62c722", + "revisionTime": "2016-04-21T14:43:05Z" }, { "path": "github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus", @@ -600,5 +602,5 @@ "revisionTime": "2016-04-21T02:29:30Z" } ], - "rootPath": "github.com/hashicorp/nomad" + "rootPath": "github.com/dkerwin/nomad" } diff --git a/website/source/docs/drivers/docker.html.md b/website/source/docs/drivers/docker.html.md index 89f83ad30..ea14e151c 100644 --- a/website/source/docs/drivers/docker.html.md +++ b/website/source/docs/drivers/docker.html.md @@ -105,6 +105,8 @@ The following options are available for use in the job specification. * `interactive` - (Optional) `true` or `false` (default). Keep STDIN open on the container. + +* `shm_size` - (Optional) The size (bytes) of /dev/shm for the container. ### Container Name