├── .gitignore ├── Godeps ├── _workspace │ ├── .gitignore │ └── src │ │ └── github.com │ │ ├── docker │ │ └── docker │ │ │ ├── api │ │ │ ├── MAINTAINERS │ │ │ ├── server │ │ │ │ └── MAINTAINERS │ │ │ ├── README.md │ │ │ ├── api_unit_test.go │ │ │ ├── common.go │ │ │ └── client │ │ │ │ ├── cli.go │ │ │ │ ├── hijack.go │ │ │ │ └── utils.go │ │ │ ├── pkg │ │ │ ├── mflag │ │ │ │ ├── MAINTAINERS │ │ │ │ ├── README.md │ │ │ │ ├── example │ │ │ │ │ └── example.go │ │ │ │ └── LICENSE │ │ │ ├── term │ │ │ │ ├── MAINTAINERS │ │ │ │ ├── termios_linux.go │ │ │ │ ├── termios_darwin.go │ │ │ │ ├── termios_freebsd.go │ │ │ │ └── term.go │ │ │ ├── parsers │ │ │ │ ├── MAINTAINERS │ │ │ │ ├── kernel │ │ │ │ │ ├── uname_unsupported.go │ │ │ │ │ ├── uname_linux.go │ │ │ │ │ ├── kernel.go │ │ │ │ │ └── kernel_test.go │ │ │ │ ├── operatingsystem │ │ │ │ │ ├── operatingsystem.go │ │ │ │ │ └── operatingsystem_test.go │ │ │ │ ├── filters │ │ │ │ │ ├── parse.go │ │ │ │ │ └── parse_test.go │ │ │ │ ├── parsers.go │ │ │ │ └── parsers_test.go │ │ │ ├── units │ │ │ │ ├── MAINTAINERS │ │ │ │ ├── duration.go │ │ │ │ ├── duration_test.go │ │ │ │ ├── size.go │ │ │ │ └── size_test.go │ │ │ ├── version │ │ │ │ ├── version_test.go │ │ │ │ └── version.go │ │ │ └── log │ │ │ │ ├── log_test.go │ │ │ │ └── log.go │ │ │ ├── engine │ │ │ ├── MAINTAINERS │ │ │ ├── helpers_test.go │ │ │ ├── hack.go │ │ │ ├── http.go │ │ │ ├── shutdown_test.go │ │ │ ├── job_test.go │ │ │ ├── table_test.go │ │ │ ├── table.go │ │ │ ├── engine_test.go │ │ │ ├── streams_test.go │ │ │ ├── streams.go │ │ │ ├── job.go │ │ │ ├── engine.go │ │ │ ├── env.go │ │ │ └── env_test.go │ │ │ ├── utils │ │ │ ├── tmpdir.go │ │ │ ├── random.go │ │ │ ├── tmpdir_unix.go │ │ │ ├── timeoutconn.go │ │ │ ├── daemon.go │ │ │ ├── timeoutconn_test.go │ │ │ ├── jsonmessage_test.go │ │ │ ├── progressreader.go │ │ │ ├── streamformatter_test.go │ │ │ ├── streamformatter.go │ │ │ ├── utils_test.go │ │ │ ├── http.go │ │ │ ├── jsonmessage.go │ │ │ └── stdcopy.go │ │ │ ├── opts │ │ │ ├── ip.go │ │ │ ├── envfile.go │ │ │ ├── opts_test.go │ │ │ └── opts.go │ │ │ └── dockerversion │ │ │ └── dockerversion.go │ │ └── fsouza │ │ └── go-dockerclient │ │ ├── .travis.yml │ │ ├── DOCKER-LICENSE │ │ ├── testing │ │ ├── data │ │ │ ├── Dockerfile │ │ │ ├── container.tar │ │ │ └── dockerfile.tar │ │ └── writer.go │ │ ├── change_test.go │ │ ├── change.go │ │ ├── LICENSE │ │ ├── signal.go │ │ ├── AUTHORS │ │ ├── README.markdown │ │ ├── misc.go │ │ ├── stdcopy.go │ │ ├── event_test.go │ │ ├── example_test.go │ │ ├── misc_test.go │ │ ├── env.go │ │ └── event.go ├── Readme └── Godeps.json ├── image ├── Dockerfile └── startup.sh └── example ├── nginx.service └── coreos-nginx.service /.gitignore: -------------------------------------------------------------------------------- 1 | bin/systemd-docker 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Victor Vieux (@vieux) 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Victor Vieux (@vieux) 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Solomon Hykes (@shykes) 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/term/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Solomon Hykes (@shykes) 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Erik Hollensbe (@erikh) 2 | -------------------------------------------------------------------------------- /image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM busybox:latest 2 | 3 | ADD systemd-docker / 4 | ADD startup.sh / 5 | RUN mkdir -p /opt/bin 6 | CMD ["/startup.sh"] 7 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/units/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Michael Crosby (@crosbymichael) 2 | Victor Vieux (@vieux) 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/server/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Victor Vieux (@vieux) 2 | # off the grid until september 3 | # Johan Euphrosine (@proppy) 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1.2 4 | - 1.2 5 | - 1.3.1 6 | - tip 7 | env: 8 | - GOARCH=amd64 9 | - GOARCH=386 10 | install: 11 | - go get -d ./... 12 | script: 13 | - go test ./... 14 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/README.md: -------------------------------------------------------------------------------- 1 | This directory contains code pertaining to the Docker API: 2 | 3 | - Used by the docker client when communicating with the docker daemon 4 | 5 | - Used by third party tools wishing to interface with the docker daemon 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/helpers_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var globalTestID string 8 | 9 | func mkJob(t *testing.T, name string, args ...string) *Job { 10 | return New().Job(name, args...) 11 | } 12 | -------------------------------------------------------------------------------- /image/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | checksum() 4 | { 5 | md5sum $1 | awk '{print $1}' 6 | } 7 | 8 | if [ ! -e /opt/bin/systemd-docker ] || [ "$(checksum /opt/bin/systemd-docker)" != "$(checksum /systemd-docker)" ]; then 9 | echo "Installing systemd-docker to /opt/bin" 10 | cp -pf /systemd-docker /opt/bin 11 | fi 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/tmpdir.go: -------------------------------------------------------------------------------- 1 | // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd 2 | 3 | package utils 4 | 5 | import ( 6 | "os" 7 | ) 8 | 9 | // TempDir returns the default directory to use for temporary files. 10 | func TempDir(rootdir string) (string error) { 11 | return os.TempDir(), nil 12 | } 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/DOCKER-LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | You can find the Docker license int the following link: 6 | https://raw2.github.com/dotcloud/docker/master/LICENSE 7 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_unsupported.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package kernel 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | type Utsname struct { 10 | Release [65]byte 11 | } 12 | 13 | func uname() (*Utsname, error) { 14 | return nil, errors.New("Kernel version detection is available only on linux") 15 | } 16 | -------------------------------------------------------------------------------- /example/nginx.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Nginx 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStart=/opt/bin/systemd-docker run --rm --name %n nginx 8 | Restart=always 9 | RestartSec=10s 10 | Type=notify 11 | NotifyAccess=all 12 | TimeoutStartSec=120 13 | TimeoutStopSec=15 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_linux.go: -------------------------------------------------------------------------------- 1 | package kernel 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | type Utsname syscall.Utsname 8 | 9 | func uname() (*syscall.Utsname, error) { 10 | uts := &syscall.Utsname{} 11 | 12 | if err := syscall.Uname(uts); err != nil { 13 | return nil, err 14 | } 15 | return uts, nil 16 | } 17 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/random.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/hex" 6 | "io" 7 | ) 8 | 9 | func RandomString() string { 10 | id := make([]byte, 32) 11 | 12 | if _, err := io.ReadFull(rand.Reader, id); err != nil { 13 | panic(err) // This shouldn't happen 14 | } 15 | return hex.EncodeToString(id) 16 | } 17 | -------------------------------------------------------------------------------- /example/coreos-nginx.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Nginx 3 | After=docker.service 4 | Requires=docker.service 5 | 6 | [Service] 7 | ExecStartPre=/usr/bin/docker run --rm -v /opt/bin:/opt/bin ibuildthecloud/systemd-docker 8 | ExecStart=/opt/bin/systemd-docker run --rm --name %n nginx 9 | Restart=always 10 | RestartSec=10s 11 | Type=notify 12 | NotifyAccess=all 13 | TimeoutStartSec=120 14 | TimeoutStopSec=15 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/api_unit_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestJsonContentType(t *testing.T) { 8 | if !MatchesContentType("application/json", "application/json") { 9 | t.Fail() 10 | } 11 | 12 | if !MatchesContentType("application/json; charset=utf-8", "application/json") { 13 | t.Fail() 14 | } 15 | 16 | if MatchesContentType("dockerapplication/json", "application/json") { 17 | t.Fail() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/hack.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | type Hack map[string]interface{} 4 | 5 | func (eng *Engine) Hack_GetGlobalVar(key string) interface{} { 6 | if eng.hack == nil { 7 | return nil 8 | } 9 | val, exists := eng.hack[key] 10 | if !exists { 11 | return nil 12 | } 13 | return val 14 | } 15 | 16 | func (eng *Engine) Hack_SetGlobalVar(key string, val interface{}) { 17 | if eng.hack == nil { 18 | eng.hack = make(Hack) 19 | } 20 | eng.hack[key] = val 21 | } 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/tmpdir_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin dragonfly freebsd linux netbsd openbsd 2 | 3 | package utils 4 | 5 | import ( 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | // TempDir returns the default directory to use for temporary files. 11 | func TempDir(rootDir string) (string, error) { 12 | var tmpDir string 13 | if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" { 14 | tmpDir = filepath.Join(rootDir, "tmp") 15 | } 16 | err := os.MkdirAll(tmpDir, 0700) 17 | return tmpDir, err 18 | } 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/opts/ip.go: -------------------------------------------------------------------------------- 1 | package opts 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | type IpOpt struct { 9 | *net.IP 10 | } 11 | 12 | func NewIpOpt(ref *net.IP, defaultVal string) *IpOpt { 13 | o := &IpOpt{ 14 | IP: ref, 15 | } 16 | o.Set(defaultVal) 17 | return o 18 | } 19 | 20 | func (o *IpOpt) Set(val string) error { 21 | ip := net.ParseIP(val) 22 | if ip == nil { 23 | return fmt.Errorf("%s is not an ip address", val) 24 | } 25 | (*o.IP) = net.ParseIP(val) 26 | return nil 27 | } 28 | 29 | func (o *IpOpt) String() string { 30 | return (*o.IP).String() 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/timeoutconn.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | func NewTimeoutConn(conn net.Conn, timeout time.Duration) net.Conn { 9 | return &TimeoutConn{conn, timeout} 10 | } 11 | 12 | // A net.Conn that sets a deadline for every Read or Write operation 13 | type TimeoutConn struct { 14 | net.Conn 15 | timeout time.Duration 16 | } 17 | 18 | func (c *TimeoutConn) Read(b []byte) (int, error) { 19 | if c.timeout > 0 { 20 | err := c.Conn.SetReadDeadline(time.Now().Add(c.timeout)) 21 | if err != nil { 22 | return 0, err 23 | } 24 | } 25 | return c.Conn.Read(b) 26 | } 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/dockerversion/dockerversion.go: -------------------------------------------------------------------------------- 1 | package dockerversion 2 | 3 | // FIXME: this should be embedded in the docker/docker.go, 4 | // but we can't because distro policy requires us to 5 | // package a separate dockerinit binary, and that binary needs 6 | // to know its version too. 7 | 8 | var ( 9 | GITCOMMIT string 10 | VERSION string 11 | 12 | IAMSTATIC bool // whether or not Docker itself was compiled statically via ./hack/make.sh binary 13 | INITSHA1 string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary 14 | INITPATH string // custom location to search for a valid dockerinit binary (available for packagers as a last resort escape hatch) 15 | ) 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/Dockerfile: -------------------------------------------------------------------------------- 1 | # this file describes how to build tsuru python image 2 | # to run it: 3 | # 1- install docker 4 | # 2- run: $ docker build -t tsuru/python https://raw.github.com/tsuru/basebuilder/master/python/Dockerfile 5 | 6 | from base:ubuntu-quantal 7 | run apt-get install wget -y --force-yes 8 | run wget http://github.com/tsuru/basebuilder/tarball/master -O basebuilder.tar.gz --no-check-certificate 9 | run mkdir /var/lib/tsuru 10 | run tar -xvf basebuilder.tar.gz -C /var/lib/tsuru --strip 1 11 | run cp /var/lib/tsuru/python/deploy /var/lib/tsuru 12 | run cp /var/lib/tsuru/base/restart /var/lib/tsuru 13 | run cp /var/lib/tsuru/base/start /var/lib/tsuru 14 | run /var/lib/tsuru/base/install 15 | run /var/lib/tsuru/base/setup 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/change_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestChangeString(t *testing.T) { 12 | var tests = []struct { 13 | change Change 14 | expected string 15 | }{ 16 | {Change{"/etc/passwd", ChangeModify}, "C /etc/passwd"}, 17 | {Change{"/etc/passwd", ChangeAdd}, "A /etc/passwd"}, 18 | {Change{"/etc/passwd", ChangeDelete}, "D /etc/passwd"}, 19 | {Change{"/etc/passwd", 33}, " /etc/passwd"}, 20 | } 21 | for _, tt := range tests { 22 | if got := tt.change.String(); got != tt.expected { 23 | t.Errorf("Change.String(): want %q. Got %q.", tt.expected, got) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/change.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import "fmt" 8 | 9 | type ChangeType int 10 | 11 | const ( 12 | ChangeModify ChangeType = iota 13 | ChangeAdd 14 | ChangeDelete 15 | ) 16 | 17 | // Change represents a change in a container. 18 | // 19 | // See http://goo.gl/DpGyzK for more details. 20 | type Change struct { 21 | Path string 22 | Kind ChangeType 23 | } 24 | 25 | func (change *Change) String() string { 26 | var kind string 27 | switch change.Kind { 28 | case ChangeModify: 29 | kind = "C" 30 | case ChangeAdd: 31 | kind = "A" 32 | case ChangeDelete: 33 | kind = "D" 34 | } 35 | return fmt.Sprintf("%s %s", kind, change.Path) 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/daemon.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "os" 8 | "strconv" 9 | ) 10 | 11 | func CreatePidFile(pidfile string) error { 12 | if pidString, err := ioutil.ReadFile(pidfile); err == nil { 13 | pid, err := strconv.Atoi(string(pidString)) 14 | if err == nil { 15 | if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil { 16 | return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile) 17 | } 18 | } 19 | } 20 | 21 | file, err := os.Create(pidfile) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | defer file.Close() 27 | 28 | _, err = fmt.Fprintf(file, "%d", os.Getpid()) 29 | return err 30 | } 31 | 32 | func RemovePidFile(pidfile string) { 33 | if err := os.Remove(pidfile); err != nil { 34 | log.Printf("Error removing %s: %s", pidfile, err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/version/version_test.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func assertVersion(t *testing.T, a, b string, result int) { 8 | if r := Version(a).compareTo(Version(b)); r != result { 9 | t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result) 10 | } 11 | } 12 | 13 | func TestCompareVersion(t *testing.T) { 14 | assertVersion(t, "1.12", "1.12", 0) 15 | assertVersion(t, "1.0.0", "1", 0) 16 | assertVersion(t, "1", "1.0.0", 0) 17 | assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1) 18 | assertVersion(t, "1", "1.0.1", -1) 19 | assertVersion(t, "1.0.1", "1", 1) 20 | assertVersion(t, "1.0.1", "1.0.2", -1) 21 | assertVersion(t, "1.0.2", "1.0.3", -1) 22 | assertVersion(t, "1.0.3", "1.1", -1) 23 | assertVersion(t, "1.1", "1.1.1", -1) 24 | assertVersion(t, "1.1.1", "1.1.2", -1) 25 | assertVersion(t, "1.1.2", "1.2", -1) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/timeoutconn_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "net/http/httptest" 9 | "testing" 10 | "time" 11 | ) 12 | 13 | func TestTimeoutConnRead(t *testing.T) { 14 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 15 | fmt.Fprintln(w, "hello") 16 | })) 17 | defer ts.Close() 18 | conn, err := net.Dial("tcp", ts.URL[7:]) 19 | if err != nil { 20 | t.Fatalf("failed to create connection to %q: %v", ts.URL, err) 21 | } 22 | tconn := NewTimeoutConn(conn, 1*time.Second) 23 | 24 | if _, err = bufio.NewReader(tconn).ReadString('\n'); err == nil { 25 | t.Fatalf("expected timeout error, got none") 26 | } 27 | if _, err := fmt.Fprintf(tconn, "GET / HTTP/1.0\r\n\r\n"); err != nil { 28 | t.Errorf("unexpected error: %v", err) 29 | } 30 | if _, err = bufio.NewReader(tconn).ReadString('\n'); err != nil { 31 | t.Errorf("unexpected error: %v", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/README.md: -------------------------------------------------------------------------------- 1 | Package mflag (aka multiple-flag) implements command-line flag parsing. 2 | It's an **hacky** fork of the [official golang package](http://golang.org/pkg/flag/) 3 | 4 | It adds: 5 | 6 | * both short and long flag version 7 | `./example -s red` `./example --string blue` 8 | 9 | * multiple names for the same option 10 | ``` 11 | $>./example -h 12 | Usage of example: 13 | -s, --string="": a simple string 14 | ``` 15 | 16 | ___ 17 | It is very flexible on purpose, so you can do things like: 18 | ``` 19 | $>./example -h 20 | Usage of example: 21 | -s, -string, --string="": a simple string 22 | ``` 23 | 24 | Or: 25 | ``` 26 | $>./example -h 27 | Usage of example: 28 | -oldflag, --newflag="": a simple string 29 | ``` 30 | 31 | You can also hide some flags from the usage, so if we want only `--newflag`: 32 | ``` 33 | $>./example -h 34 | Usage of example: 35 | --newflag="": a simple string 36 | $>./example -oldflag str 37 | str 38 | ``` 39 | 40 | See [example.go](example/example.go) for more details. 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem.go: -------------------------------------------------------------------------------- 1 | package operatingsystem 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io/ioutil" 7 | ) 8 | 9 | var ( 10 | // file to use to detect if the daemon is running in a container 11 | proc1Cgroup = "/proc/1/cgroup" 12 | 13 | // file to check to determine Operating System 14 | etcOsRelease = "/etc/os-release" 15 | ) 16 | 17 | func GetOperatingSystem() (string, error) { 18 | b, err := ioutil.ReadFile(etcOsRelease) 19 | if err != nil { 20 | return "", err 21 | } 22 | if i := bytes.Index(b, []byte("PRETTY_NAME")); i >= 0 { 23 | b = b[i+13:] 24 | return string(b[:bytes.IndexByte(b, '"')]), nil 25 | } 26 | return "", errors.New("PRETTY_NAME not found") 27 | } 28 | 29 | func IsContainerized() (bool, error) { 30 | b, err := ioutil.ReadFile(proc1Cgroup) 31 | if err != nil { 32 | return false, err 33 | } 34 | for _, line := range bytes.Split(b, []byte{'\n'}) { 35 | if len(line) > 0 && !bytes.HasSuffix(line, []byte{'/'}) { 36 | return true, nil 37 | } 38 | } 39 | return false, nil 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/units/duration.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // HumanDuration returns a human-readable approximation of a duration 9 | // (eg. "About a minute", "4 hours ago", etc.) 10 | func HumanDuration(d time.Duration) string { 11 | if seconds := int(d.Seconds()); seconds < 1 { 12 | return "Less than a second" 13 | } else if seconds < 60 { 14 | return fmt.Sprintf("%d seconds", seconds) 15 | } else if minutes := int(d.Minutes()); minutes == 1 { 16 | return "About a minute" 17 | } else if minutes < 60 { 18 | return fmt.Sprintf("%d minutes", minutes) 19 | } else if hours := int(d.Hours()); hours == 1 { 20 | return "About an hour" 21 | } else if hours < 48 { 22 | return fmt.Sprintf("%d hours", hours) 23 | } else if hours < 24*7*2 { 24 | return fmt.Sprintf("%d days", hours/24) 25 | } else if hours < 24*30*3 { 26 | return fmt.Sprintf("%d weeks", hours/24/7) 27 | } else if hours < 24*365*2 { 28 | return fmt.Sprintf("%d months", hours/24/30) 29 | } 30 | return fmt.Sprintf("%f years", d.Hours()/24/365) 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/writer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testing 6 | 7 | import ( 8 | "encoding/binary" 9 | "errors" 10 | "io" 11 | ) 12 | 13 | type stdType [8]byte 14 | 15 | var ( 16 | stdin stdType = stdType{0: 0} 17 | stdout stdType = stdType{0: 1} 18 | stderr stdType = stdType{0: 2} 19 | ) 20 | 21 | type stdWriter struct { 22 | io.Writer 23 | prefix stdType 24 | sizeBuf []byte 25 | } 26 | 27 | func (w *stdWriter) Write(buf []byte) (n int, err error) { 28 | if w == nil || w.Writer == nil { 29 | return 0, errors.New("Writer not instanciated") 30 | } 31 | binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf))) 32 | buf = append(w.prefix[:], buf...) 33 | 34 | n, err = w.Writer.Write(buf) 35 | return n - 8, err 36 | } 37 | 38 | func newStdWriter(w io.Writer, t stdType) *stdWriter { 39 | if len(t) != 8 { 40 | return nil 41 | } 42 | return &stdWriter{Writer: w, prefix: t, sizeBuf: make([]byte, 4)} 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/log/log_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "regexp" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestLogFatalf(t *testing.T) { 11 | var output *bytes.Buffer 12 | 13 | tests := []struct { 14 | Level priority 15 | Format string 16 | Values []interface{} 17 | ExpectedPattern string 18 | }{ 19 | {fatal, "%d + %d = %d", []interface{}{1, 1, 2}, "\\[fatal\\] testing.go:\\d+ 1 \\+ 1 = 2"}, 20 | {error, "%d + %d = %d", []interface{}{1, 1, 2}, "\\[error\\] testing.go:\\d+ 1 \\+ 1 = 2"}, 21 | {info, "%d + %d = %d", []interface{}{1, 1, 2}, "\\[info\\] 1 \\+ 1 = 2"}, 22 | {debug, "%d + %d = %d", []interface{}{1, 1, 2}, "\\[debug\\] testing.go:\\d+ 1 \\+ 1 = 2"}, 23 | } 24 | 25 | for i, test := range tests { 26 | output = &bytes.Buffer{} 27 | logf(output, test.Level, test.Format, test.Values...) 28 | 29 | expected := regexp.MustCompile(test.ExpectedPattern) 30 | if !expected.MatchString(output.String()) { 31 | t.Errorf("[%d] Log output does not match expected pattern:\n\tExpected: %s\n\tOutput: %s", 32 | i, 33 | expected.String(), 34 | output.String()) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/jsonmessage_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestError(t *testing.T) { 8 | je := JSONError{404, "Not found"} 9 | if je.Error() != "Not found" { 10 | t.Fatalf("Expected 'Not found' got '%s'", je.Error()) 11 | } 12 | } 13 | 14 | func TestProgress(t *testing.T) { 15 | jp := JSONProgress{} 16 | if jp.String() != "" { 17 | t.Fatalf("Expected empty string, got '%s'", jp.String()) 18 | } 19 | 20 | expected := " 1 B" 21 | jp2 := JSONProgress{Current: 1} 22 | if jp2.String() != expected { 23 | t.Fatalf("Expected %q, got %q", expected, jp2.String()) 24 | } 25 | 26 | expected = "[=========================> ] 50 B/100 B" 27 | jp3 := JSONProgress{Current: 50, Total: 100} 28 | if jp3.String() != expected { 29 | t.Fatalf("Expected %q, got %q", expected, jp3.String()) 30 | } 31 | 32 | // this number can't be negetive gh#7136 33 | expected = "[==============================================================>] 50 B/40 B" 34 | jp4 := JSONProgress{Current: 50, Total: 40} 35 | if jp4.String() != expected { 36 | t.Fatalf("Expected %q, got %q", expected, jp4.String()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | type Version string 9 | 10 | func (me Version) compareTo(other Version) int { 11 | var ( 12 | meTab = strings.Split(string(me), ".") 13 | otherTab = strings.Split(string(other), ".") 14 | ) 15 | 16 | max := len(meTab) 17 | if len(otherTab) > max { 18 | max = len(otherTab) 19 | } 20 | for i := 0; i < max; i++ { 21 | var meInt, otherInt int 22 | 23 | if len(meTab) > i { 24 | meInt, _ = strconv.Atoi(meTab[i]) 25 | } 26 | if len(otherTab) > i { 27 | otherInt, _ = strconv.Atoi(otherTab[i]) 28 | } 29 | if meInt > otherInt { 30 | return 1 31 | } 32 | if otherInt > meInt { 33 | return -1 34 | } 35 | } 36 | return 0 37 | } 38 | 39 | func (me Version) LessThan(other Version) bool { 40 | return me.compareTo(other) == -1 41 | } 42 | 43 | func (me Version) LessThanOrEqualTo(other Version) bool { 44 | return me.compareTo(other) <= 0 45 | } 46 | 47 | func (me Version) GreaterThan(other Version) bool { 48 | return me.compareTo(other) == 1 49 | } 50 | 51 | func (me Version) GreaterThanOrEqualTo(other Version) bool { 52 | return me.compareTo(other) >= 0 53 | } 54 | 55 | func (me Version) Equal(other Version) bool { 56 | return me.compareTo(other) == 0 57 | } 58 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/example/example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | flag "github.com/docker/docker/pkg/mflag" 7 | ) 8 | 9 | var ( 10 | i int 11 | str string 12 | b, b2, h bool 13 | ) 14 | 15 | func init() { 16 | flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp") 17 | flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool") 18 | flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool") 19 | flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool") 20 | flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer") 21 | flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage 22 | flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help") 23 | flag.StringVar(&str, []string{"mode"}, "mode1", "set the mode\nmode1: use the mode1\nmode2: use the mode2\nmode3: use the mode3") 24 | flag.Parse() 25 | } 26 | func main() { 27 | if h { 28 | flag.PrintDefaults() 29 | } else { 30 | fmt.Printf("s/#hidden/-string: %s\n", str) 31 | fmt.Printf("b: %t\n", b) 32 | fmt.Printf("-bool: %t\n", b2) 33 | fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String()) 34 | fmt.Printf("ARGS: %v\n", flag.Args()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/term/termios_linux.go: -------------------------------------------------------------------------------- 1 | package term 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | getTermios = syscall.TCGETS 10 | setTermios = syscall.TCSETS 11 | ) 12 | 13 | type Termios struct { 14 | Iflag uint32 15 | Oflag uint32 16 | Cflag uint32 17 | Lflag uint32 18 | Cc [20]byte 19 | Ispeed uint32 20 | Ospeed uint32 21 | } 22 | 23 | // MakeRaw put the terminal connected to the given file descriptor into raw 24 | // mode and returns the previous state of the terminal so that it can be 25 | // restored. 26 | func MakeRaw(fd uintptr) (*State, error) { 27 | var oldState State 28 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 29 | return nil, err 30 | } 31 | 32 | newState := oldState.termios 33 | 34 | newState.Iflag &^= (syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON) 35 | newState.Oflag &^= syscall.OPOST 36 | newState.Lflag &^= (syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN) 37 | newState.Cflag &^= (syscall.CSIZE | syscall.PARENB) 38 | newState.Cflag |= syscall.CS8 39 | 40 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { 41 | return nil, err 42 | } 43 | return &oldState, nil 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, go-dockerclient authors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/signal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | // Signal represents a signal that can be send to the container on 8 | // KillContainer call. 9 | type Signal int 10 | 11 | // These values represent all signals available on Linux, where containers will 12 | // be running. 13 | const ( 14 | SIGABRT = Signal(0x6) 15 | SIGALRM = Signal(0xe) 16 | SIGBUS = Signal(0x7) 17 | SIGCHLD = Signal(0x11) 18 | SIGCLD = Signal(0x11) 19 | SIGCONT = Signal(0x12) 20 | SIGFPE = Signal(0x8) 21 | SIGHUP = Signal(0x1) 22 | SIGILL = Signal(0x4) 23 | SIGINT = Signal(0x2) 24 | SIGIO = Signal(0x1d) 25 | SIGIOT = Signal(0x6) 26 | SIGKILL = Signal(0x9) 27 | SIGPIPE = Signal(0xd) 28 | SIGPOLL = Signal(0x1d) 29 | SIGPROF = Signal(0x1b) 30 | SIGPWR = Signal(0x1e) 31 | SIGQUIT = Signal(0x3) 32 | SIGSEGV = Signal(0xb) 33 | SIGSTKFLT = Signal(0x10) 34 | SIGSTOP = Signal(0x13) 35 | SIGSYS = Signal(0x1f) 36 | SIGTERM = Signal(0xf) 37 | SIGTRAP = Signal(0x5) 38 | SIGTSTP = Signal(0x14) 39 | SIGTTIN = Signal(0x15) 40 | SIGTTOU = Signal(0x16) 41 | SIGUNUSED = Signal(0x1f) 42 | SIGURG = Signal(0x17) 43 | SIGUSR1 = Signal(0xa) 44 | SIGUSR2 = Signal(0xc) 45 | SIGVTALRM = Signal(0x1a) 46 | SIGWINCH = Signal(0x1c) 47 | SIGXCPU = Signal(0x18) 48 | SIGXFSZ = Signal(0x19) 49 | ) 50 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of go-dockerclient authors for copyright purposes. 2 | 3 | Andreas Jaekle 4 | Andrews Medina 5 | Andy Goldstein 6 | Ben McCann 7 | Cezar Sa Espinola 8 | Cheah Chu Yeow 9 | cheneydeng 10 | Ed 11 | Eric Anderson 12 | Fabio Rehm 13 | Flavia Missi 14 | Francisco Souza 15 | Jari Kolehmainen 16 | Jason Wilder 17 | Jean-Baptiste Dalido 18 | Jeff Mitchell 19 | Jeffrey Hulten 20 | Johan Euphrosine 21 | Karan Misra 22 | Lucas Clemente 23 | Omeid Matten 24 | Paul Morie 25 | Peter Jihoon Kim 26 | Philippe Lafoucrière 27 | Rafe Colton 28 | Salvador Gironès 29 | Simon Eskildsen 30 | Simon Menke 31 | Skolos 32 | Soulou 33 | Sridhar Ratnakumar 34 | Summer Mousa 35 | Tarsis Azevedo 36 | Tim Schindler 37 | Wiliam Souza 38 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/README.markdown: -------------------------------------------------------------------------------- 1 | #go-dockerclient 2 | 3 | [![Build Status](https://drone.io/github.com/fsouza/go-dockerclient/status.png)](https://drone.io/github.com/fsouza/go-dockerclient/latest) 4 | [![Build Status](https://travis-ci.org/fsouza/go-dockerclient.png)](https://travis-ci.org/fsouza/go-dockerclient) 5 | 6 | [![GoDoc](http://godoc.org/github.com/fsouza/go-dockerclient?status.png)](http://godoc.org/github.com/fsouza/go-dockerclient) 7 | 8 | This package presents a client for the Docker remote API. 9 | 10 | For more details, check the [remote API documentation](http://docs.docker.io/en/latest/reference/api/docker_remote_api/). 11 | 12 | ## Example 13 | 14 | ```go 15 | package main 16 | 17 | import ( 18 | "fmt" 19 | "github.com/fsouza/go-dockerclient" 20 | ) 21 | 22 | func main() { 23 | endpoint := "unix:///var/run/docker.sock" 24 | client, _ := docker.NewClient(endpoint) 25 | imgs, _ := client.ListImages(true) 26 | for _, img := range imgs { 27 | fmt.Println("ID: ", img.ID) 28 | fmt.Println("RepoTags: ", img.RepoTags) 29 | fmt.Println("Created: ", img.Created) 30 | fmt.Println("Size: ", img.Size) 31 | fmt.Println("VirtualSize: ", img.VirtualSize) 32 | fmt.Println("ParentId: ", img.ParentId) 33 | fmt.Println("Repository: ", img.Repository) 34 | } 35 | } 36 | ``` 37 | 38 | ## Developing 39 | 40 | You can run the tests with: 41 | 42 | go get -d ./... 43 | go test ./... 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/common.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "mime" 6 | "strings" 7 | 8 | "github.com/docker/docker/engine" 9 | "github.com/docker/docker/pkg/log" 10 | "github.com/docker/docker/pkg/parsers" 11 | "github.com/docker/docker/pkg/version" 12 | ) 13 | 14 | const ( 15 | APIVERSION version.Version = "1.14" 16 | DEFAULTHTTPHOST = "127.0.0.1" 17 | DEFAULTUNIXSOCKET = "/var/run/docker.sock" 18 | ) 19 | 20 | func ValidateHost(val string) (string, error) { 21 | host, err := parsers.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val) 22 | if err != nil { 23 | return val, err 24 | } 25 | return host, nil 26 | } 27 | 28 | //TODO remove, used on < 1.5 in getContainersJSON 29 | func DisplayablePorts(ports *engine.Table) string { 30 | result := []string{} 31 | ports.SetKey("PublicPort") 32 | ports.Sort() 33 | for _, port := range ports.Data { 34 | if port.Get("IP") == "" { 35 | result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PrivatePort"), port.Get("Type"))) 36 | } else { 37 | result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type"))) 38 | } 39 | } 40 | return strings.Join(result, ", ") 41 | } 42 | 43 | func MatchesContentType(contentType, expectedType string) bool { 44 | mimetype, _, err := mime.ParseMediaType(contentType) 45 | if err != nil { 46 | log.Errorf("Error parsing media type: %s error: %s", contentType, err.Error()) 47 | } 48 | return err == nil && mimetype == expectedType 49 | } 50 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/filters/parse.go: -------------------------------------------------------------------------------- 1 | package filters 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "strings" 7 | ) 8 | 9 | type Args map[string][]string 10 | 11 | // Parse the argument to the filter flag. Like 12 | // 13 | // `docker ps -f 'created=today' -f 'image.name=ubuntu*'` 14 | // 15 | // If prev map is provided, then it is appended to, and returned. By default a new 16 | // map is created. 17 | func ParseFlag(arg string, prev Args) (Args, error) { 18 | var filters Args = prev 19 | if prev == nil { 20 | filters = Args{} 21 | } 22 | if len(arg) == 0 { 23 | return filters, nil 24 | } 25 | 26 | if !strings.Contains(arg, "=") { 27 | return filters, ErrorBadFormat 28 | } 29 | 30 | f := strings.SplitN(arg, "=", 2) 31 | filters[f[0]] = append(filters[f[0]], f[1]) 32 | 33 | return filters, nil 34 | } 35 | 36 | var ErrorBadFormat = errors.New("bad format of filter (expected name=value)") 37 | 38 | // packs the Args into an string for easy transport from client to server 39 | func ToParam(a Args) (string, error) { 40 | // this way we don't URL encode {}, just empty space 41 | if len(a) == 0 { 42 | return "", nil 43 | } 44 | 45 | buf, err := json.Marshal(a) 46 | if err != nil { 47 | return "", err 48 | } 49 | return string(buf), nil 50 | } 51 | 52 | // unpacks the filter Args 53 | func FromParam(p string) (Args, error) { 54 | args := Args{} 55 | if len(p) == 0 { 56 | return args, nil 57 | } 58 | err := json.Unmarshal([]byte(p), &args) 59 | if err != nil { 60 | return nil, err 61 | } 62 | return args, nil 63 | } 64 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/opts/envfile.go: -------------------------------------------------------------------------------- 1 | package opts 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | /* 11 | Read in a line delimited file with environment variables enumerated 12 | */ 13 | func ParseEnvFile(filename string) ([]string, error) { 14 | fh, err := os.Open(filename) 15 | if err != nil { 16 | return []string{}, err 17 | } 18 | defer fh.Close() 19 | 20 | lines := []string{} 21 | scanner := bufio.NewScanner(fh) 22 | for scanner.Scan() { 23 | line := scanner.Text() 24 | // line is not empty, and not starting with '#' 25 | if len(line) > 0 && !strings.HasPrefix(line, "#") { 26 | if strings.Contains(line, "=") { 27 | data := strings.SplitN(line, "=", 2) 28 | 29 | // trim the front of a variable, but nothing else 30 | variable := strings.TrimLeft(data[0], whiteSpaces) 31 | if strings.ContainsAny(variable, whiteSpaces) { 32 | return []string{}, ErrBadEnvVariable{fmt.Sprintf("variable '%s' has white spaces", variable)} 33 | } 34 | 35 | // pass the value through, no trimming 36 | lines = append(lines, fmt.Sprintf("%s=%s", variable, data[1])) 37 | } else { 38 | // if only a pass-through variable is given, clean it up. 39 | lines = append(lines, fmt.Sprintf("%s=%s", strings.TrimSpace(line), os.Getenv(line))) 40 | } 41 | } 42 | } 43 | return lines, nil 44 | } 45 | 46 | var whiteSpaces = " \t" 47 | 48 | type ErrBadEnvVariable struct { 49 | msg string 50 | } 51 | 52 | func (e ErrBadEnvVariable) Error() string { 53 | return fmt.Sprintf("poorly formatted environment: %s", e.msg) 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 The Docker & Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/http.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "net/http" 5 | "path" 6 | ) 7 | 8 | // ServeHTTP executes a job as specified by the http request `r`, and sends the 9 | // result as an http response. 10 | // This method allows an Engine instance to be passed as a standard http.Handler interface. 11 | // 12 | // Note that the protocol used in this method is a convenience wrapper and is not the canonical 13 | // implementation of remote job execution. This is because HTTP/1 does not handle stream multiplexing, 14 | // and so cannot differentiate stdout from stderr. Additionally, headers cannot be added to a response 15 | // once data has been written to the body, which makes it inconvenient to return metadata such 16 | // as the exit status. 17 | // 18 | func (eng *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) { 19 | var ( 20 | jobName = path.Base(r.URL.Path) 21 | jobArgs, exists = r.URL.Query()["a"] 22 | ) 23 | if !exists { 24 | jobArgs = []string{} 25 | } 26 | w.Header().Set("Job-Name", jobName) 27 | for _, arg := range jobArgs { 28 | w.Header().Add("Job-Args", arg) 29 | } 30 | job := eng.Job(jobName, jobArgs...) 31 | job.Stdout.Add(w) 32 | job.Stderr.Add(w) 33 | // FIXME: distinguish job status from engine error in Run() 34 | // The former should be passed as a special header, the former 35 | // should cause a 500 status 36 | w.WriteHeader(http.StatusOK) 37 | // The exit status cannot be sent reliably with HTTP1, because headers 38 | // can only be sent before the body. 39 | // (we could possibly use http footers via chunked encoding, but I couldn't find 40 | // how to use them in net/http) 41 | job.Run() 42 | } 43 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/misc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "bytes" 9 | "strings" 10 | ) 11 | 12 | // Version returns version information about the docker server. 13 | // 14 | // See http://goo.gl/IqKNRE for more details. 15 | func (c *Client) Version() (*Env, error) { 16 | body, _, err := c.do("GET", "/version", nil) 17 | if err != nil { 18 | return nil, err 19 | } 20 | var env Env 21 | if err := env.Decode(bytes.NewReader(body)); err != nil { 22 | return nil, err 23 | } 24 | return &env, nil 25 | } 26 | 27 | // Info returns system-wide information, like the number of running containers. 28 | // 29 | // See http://goo.gl/LOmySw for more details. 30 | func (c *Client) Info() (*Env, error) { 31 | body, _, err := c.do("GET", "/info", nil) 32 | if err != nil { 33 | return nil, err 34 | } 35 | var info Env 36 | err = info.Decode(bytes.NewReader(body)) 37 | if err != nil { 38 | return nil, err 39 | } 40 | return &info, nil 41 | } 42 | 43 | // ParseRepositoryTag gets the name of the repository and returns it splitted 44 | // in two parts: the repository and the tag. 45 | // 46 | // Some examples: 47 | // 48 | // localhost.localdomain:5000/samalba/hipache:latest -> localhost.localdomain:5000/samalba/hipache, latest 49 | // localhost.localdomain:5000/samalba/hipache -> localhost.localdomain:5000/samalba/hipache, "" 50 | func ParseRepositoryTag(repoTag string) (repository string, tag string) { 51 | n := strings.LastIndex(repoTag, ":") 52 | if n < 0 { 53 | return repoTag, "" 54 | } 55 | if tag := repoTag[n+1:]; !strings.Contains(tag, "/") { 56 | return repoTag[:n], tag 57 | } 58 | return repoTag, "" 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/progressreader.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "io" 5 | "time" 6 | ) 7 | 8 | // Reader with progress bar 9 | type progressReader struct { 10 | reader io.ReadCloser // Stream to read from 11 | output io.Writer // Where to send progress bar to 12 | progress JSONProgress 13 | lastUpdate int // How many bytes read at least update 14 | ID string 15 | action string 16 | sf *StreamFormatter 17 | newLine bool 18 | } 19 | 20 | func (r *progressReader) Read(p []byte) (n int, err error) { 21 | read, err := r.reader.Read(p) 22 | r.progress.Current += read 23 | updateEvery := 1024 * 512 //512kB 24 | if r.progress.Total > 0 { 25 | // Update progress for every 1% read if 1% < 512kB 26 | if increment := int(0.01 * float64(r.progress.Total)); increment < updateEvery { 27 | updateEvery = increment 28 | } 29 | } 30 | if r.progress.Current-r.lastUpdate > updateEvery || err != nil { 31 | r.output.Write(r.sf.FormatProgress(r.ID, r.action, &r.progress)) 32 | r.lastUpdate = r.progress.Current 33 | } 34 | // Send newline when complete 35 | if r.newLine && err != nil && read == 0 { 36 | r.output.Write(r.sf.FormatStatus("", "")) 37 | } 38 | return read, err 39 | } 40 | func (r *progressReader) Close() error { 41 | r.progress.Current = r.progress.Total 42 | r.output.Write(r.sf.FormatProgress(r.ID, r.action, &r.progress)) 43 | return r.reader.Close() 44 | } 45 | func ProgressReader(r io.ReadCloser, size int, output io.Writer, sf *StreamFormatter, newline bool, ID, action string) *progressReader { 46 | return &progressReader{ 47 | reader: r, 48 | output: NewWriteFlusher(output), 49 | ID: ID, 50 | action: action, 51 | progress: JSONProgress{Total: size, Start: time.Now().UTC().Unix()}, 52 | sf: sf, 53 | newLine: newline, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/term/termios_darwin.go: -------------------------------------------------------------------------------- 1 | package term 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | getTermios = syscall.TIOCGETA 10 | setTermios = syscall.TIOCSETA 11 | 12 | IGNBRK = syscall.IGNBRK 13 | PARMRK = syscall.PARMRK 14 | INLCR = syscall.INLCR 15 | IGNCR = syscall.IGNCR 16 | ECHONL = syscall.ECHONL 17 | CSIZE = syscall.CSIZE 18 | ICRNL = syscall.ICRNL 19 | ISTRIP = syscall.ISTRIP 20 | PARENB = syscall.PARENB 21 | ECHO = syscall.ECHO 22 | ICANON = syscall.ICANON 23 | ISIG = syscall.ISIG 24 | IXON = syscall.IXON 25 | BRKINT = syscall.BRKINT 26 | INPCK = syscall.INPCK 27 | OPOST = syscall.OPOST 28 | CS8 = syscall.CS8 29 | IEXTEN = syscall.IEXTEN 30 | ) 31 | 32 | type Termios struct { 33 | Iflag uint64 34 | Oflag uint64 35 | Cflag uint64 36 | Lflag uint64 37 | Cc [20]byte 38 | Ispeed uint64 39 | Ospeed uint64 40 | } 41 | 42 | // MakeRaw put the terminal connected to the given file descriptor into raw 43 | // mode and returns the previous state of the terminal so that it can be 44 | // restored. 45 | func MakeRaw(fd uintptr) (*State, error) { 46 | var oldState State 47 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 48 | return nil, err 49 | } 50 | 51 | newState := oldState.termios 52 | newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON) 53 | newState.Oflag &^= OPOST 54 | newState.Lflag &^= (ECHO | ECHONL | ICANON | ISIG | IEXTEN) 55 | newState.Cflag &^= (CSIZE | PARENB) 56 | newState.Cflag |= CS8 57 | newState.Cc[syscall.VMIN] = 1 58 | newState.Cc[syscall.VTIME] = 0 59 | 60 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { 61 | return nil, err 62 | } 63 | 64 | return &oldState, nil 65 | } 66 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/term/termios_freebsd.go: -------------------------------------------------------------------------------- 1 | package term 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | getTermios = syscall.TIOCGETA 10 | setTermios = syscall.TIOCSETA 11 | 12 | IGNBRK = syscall.IGNBRK 13 | PARMRK = syscall.PARMRK 14 | INLCR = syscall.INLCR 15 | IGNCR = syscall.IGNCR 16 | ECHONL = syscall.ECHONL 17 | CSIZE = syscall.CSIZE 18 | ICRNL = syscall.ICRNL 19 | ISTRIP = syscall.ISTRIP 20 | PARENB = syscall.PARENB 21 | ECHO = syscall.ECHO 22 | ICANON = syscall.ICANON 23 | ISIG = syscall.ISIG 24 | IXON = syscall.IXON 25 | BRKINT = syscall.BRKINT 26 | INPCK = syscall.INPCK 27 | OPOST = syscall.OPOST 28 | CS8 = syscall.CS8 29 | IEXTEN = syscall.IEXTEN 30 | ) 31 | 32 | type Termios struct { 33 | Iflag uint32 34 | Oflag uint32 35 | Cflag uint32 36 | Lflag uint32 37 | Cc [20]byte 38 | Ispeed uint32 39 | Ospeed uint32 40 | } 41 | 42 | // MakeRaw put the terminal connected to the given file descriptor into raw 43 | // mode and returns the previous state of the terminal so that it can be 44 | // restored. 45 | func MakeRaw(fd uintptr) (*State, error) { 46 | var oldState State 47 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 48 | return nil, err 49 | } 50 | 51 | newState := oldState.termios 52 | newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON) 53 | newState.Oflag &^= OPOST 54 | newState.Lflag &^= (ECHO | ECHONL | ICANON | ISIG | IEXTEN) 55 | newState.Cflag &^= (CSIZE | PARENB) 56 | newState.Cflag |= CS8 57 | newState.Cc[syscall.VMIN] = 1 58 | newState.Cc[syscall.VTIME] = 0 59 | 60 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { 61 | return nil, err 62 | } 63 | 64 | return &oldState, nil 65 | } 66 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/filters/parse_test.go: -------------------------------------------------------------------------------- 1 | package filters 2 | 3 | import ( 4 | "sort" 5 | "testing" 6 | ) 7 | 8 | func TestParseArgs(t *testing.T) { 9 | // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'` 10 | flagArgs := []string{ 11 | "created=today", 12 | "image.name=ubuntu*", 13 | "image.name=*untu", 14 | } 15 | var ( 16 | args = Args{} 17 | err error 18 | ) 19 | for i := range flagArgs { 20 | args, err = ParseFlag(flagArgs[i], args) 21 | if err != nil { 22 | t.Errorf("failed to parse %s: %s", flagArgs[i], err) 23 | } 24 | } 25 | if len(args["created"]) != 1 { 26 | t.Errorf("failed to set this arg") 27 | } 28 | if len(args["image.name"]) != 2 { 29 | t.Errorf("the args should have collapsed") 30 | } 31 | } 32 | 33 | func TestParam(t *testing.T) { 34 | a := Args{ 35 | "created": []string{"today"}, 36 | "image.name": []string{"ubuntu*", "*untu"}, 37 | } 38 | 39 | v, err := ToParam(a) 40 | if err != nil { 41 | t.Errorf("failed to marshal the filters: %s", err) 42 | } 43 | v1, err := FromParam(v) 44 | if err != nil { 45 | t.Errorf("%s", err) 46 | } 47 | for key, vals := range v1 { 48 | if _, ok := a[key]; !ok { 49 | t.Errorf("could not find key %s in original set", key) 50 | } 51 | sort.Strings(vals) 52 | sort.Strings(a[key]) 53 | if len(vals) != len(a[key]) { 54 | t.Errorf("value lengths ought to match") 55 | continue 56 | } 57 | for i := range vals { 58 | if vals[i] != a[key][i] { 59 | t.Errorf("expected %s, but got %s", a[key][i], vals[i]) 60 | } 61 | } 62 | } 63 | } 64 | 65 | func TestEmpty(t *testing.T) { 66 | a := Args{} 67 | v, err := ToParam(a) 68 | if err != nil { 69 | t.Errorf("failed to marshal the filters: %s", err) 70 | } 71 | v1, err := FromParam(v) 72 | if err != nil { 73 | t.Errorf("%s", err) 74 | } 75 | if len(a) != len(v1) { 76 | t.Errorf("these should both be empty sets") 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "runtime" 8 | "strings" 9 | ) 10 | 11 | type priority int 12 | 13 | const ( 14 | errorFormat = "[%s] %s:%d %s\n" 15 | logFormat = "[%s] %s\n" 16 | 17 | fatal priority = iota 18 | error 19 | info 20 | debug 21 | ) 22 | 23 | // A common interface to access the Fatal method of 24 | // both testing.B and testing.T. 25 | type Fataler interface { 26 | Fatal(args ...interface{}) 27 | } 28 | 29 | func (p priority) String() string { 30 | switch p { 31 | case fatal: 32 | return "fatal" 33 | case error: 34 | return "error" 35 | case info: 36 | return "info" 37 | case debug: 38 | return "debug" 39 | } 40 | 41 | return "" 42 | } 43 | 44 | // Debug function, if the debug flag is set, then display. Do nothing otherwise 45 | // If Docker is in damon mode, also send the debug info on the socket 46 | func Debugf(format string, a ...interface{}) { 47 | if os.Getenv("DEBUG") != "" { 48 | logf(os.Stderr, debug, format, a...) 49 | } 50 | } 51 | 52 | func Infof(format string, a ...interface{}) { 53 | logf(os.Stdout, info, format, a...) 54 | } 55 | 56 | func Errorf(format string, a ...interface{}) { 57 | logf(os.Stderr, error, format, a...) 58 | } 59 | 60 | func Fatalf(format string, a ...interface{}) { 61 | logf(os.Stderr, fatal, format, a...) 62 | os.Exit(1) 63 | } 64 | 65 | func logf(stream io.Writer, level priority, format string, a ...interface{}) { 66 | var prefix string 67 | 68 | if level <= error || level == debug { 69 | // Retrieve the stack infos 70 | _, file, line, ok := runtime.Caller(2) 71 | if !ok { 72 | file = "" 73 | line = -1 74 | } else { 75 | file = file[strings.LastIndex(file, "/")+1:] 76 | } 77 | prefix = fmt.Sprintf(errorFormat, level.String(), file, line, format) 78 | } else { 79 | prefix = fmt.Sprintf(logFormat, level.String(), format) 80 | } 81 | 82 | fmt.Fprintf(stream, prefix, a...) 83 | } 84 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/container.tar: -------------------------------------------------------------------------------- 1 | fakecontainer000644 000766 000024 00000000065 12210121775 016021 0ustar00flavia.carlettestaff000000 000000 this is supposed to be a fake container in a tar. xD 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/streamformatter_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "reflect" 7 | "testing" 8 | ) 9 | 10 | func TestFormatStream(t *testing.T) { 11 | sf := NewStreamFormatter(true) 12 | res := sf.FormatStream("stream") 13 | if string(res) != `{"stream":"stream"}`+"\r\n" { 14 | t.Fatalf("%q", res) 15 | } 16 | } 17 | 18 | func TestFormatStatus(t *testing.T) { 19 | sf := NewStreamFormatter(true) 20 | res := sf.FormatStatus("ID", "%s%d", "a", 1) 21 | if string(res) != `{"status":"a1","id":"ID"}`+"\r\n" { 22 | t.Fatalf("%q", res) 23 | } 24 | } 25 | 26 | func TestFormatSimpleError(t *testing.T) { 27 | sf := NewStreamFormatter(true) 28 | res := sf.FormatError(errors.New("Error for formatter")) 29 | if string(res) != `{"errorDetail":{"message":"Error for formatter"},"error":"Error for formatter"}`+"\r\n" { 30 | t.Fatalf("%q", res) 31 | } 32 | } 33 | 34 | func TestFormatJSONError(t *testing.T) { 35 | sf := NewStreamFormatter(true) 36 | err := &JSONError{Code: 50, Message: "Json error"} 37 | res := sf.FormatError(err) 38 | if string(res) != `{"errorDetail":{"code":50,"message":"Json error"},"error":"Json error"}`+"\r\n" { 39 | t.Fatalf("%q", res) 40 | } 41 | } 42 | 43 | func TestFormatProgress(t *testing.T) { 44 | sf := NewStreamFormatter(true) 45 | progress := &JSONProgress{ 46 | Current: 15, 47 | Total: 30, 48 | Start: 1, 49 | } 50 | res := sf.FormatProgress("id", "action", progress) 51 | msg := &JSONMessage{} 52 | if err := json.Unmarshal(res, msg); err != nil { 53 | t.Fatal(err) 54 | } 55 | if msg.ID != "id" { 56 | t.Fatalf("ID must be 'id', got: %s", msg.ID) 57 | } 58 | if msg.Status != "action" { 59 | t.Fatalf("Status must be 'action', got: %s", msg.Status) 60 | } 61 | if msg.ProgressMessage != progress.String() { 62 | t.Fatalf("ProgressMessage must be %s, got: %s", progress.String(), msg.ProgressMessage) 63 | } 64 | if !reflect.DeepEqual(msg.Progress, progress) { 65 | t.Fatal("Original progress not equals progress from FormatProgress") 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/ibuildthecloud/systemd-docker", 3 | "GoVersion": "go1.2.2", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/docker/docker/api", 7 | "Comment": "v1.2.0-11-g6bc773b", 8 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 9 | }, 10 | { 11 | "ImportPath": "github.com/docker/docker/dockerversion", 12 | "Comment": "v1.2.0-11-g6bc773b", 13 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 14 | }, 15 | { 16 | "ImportPath": "github.com/docker/docker/engine", 17 | "Comment": "v1.2.0-11-g6bc773b", 18 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 19 | }, 20 | { 21 | "ImportPath": "github.com/docker/docker/opts", 22 | "Comment": "v1.2.0-11-g6bc773b", 23 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 24 | }, 25 | { 26 | "ImportPath": "github.com/docker/docker/pkg/log", 27 | "Comment": "v1.2.0-11-g6bc773b", 28 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 29 | }, 30 | { 31 | "ImportPath": "github.com/docker/docker/pkg/mflag", 32 | "Comment": "v1.2.0-11-g6bc773b", 33 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 34 | }, 35 | { 36 | "ImportPath": "github.com/docker/docker/pkg/parsers", 37 | "Comment": "v1.2.0-11-g6bc773b", 38 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 39 | }, 40 | { 41 | "ImportPath": "github.com/docker/docker/pkg/term", 42 | "Comment": "v1.2.0-11-g6bc773b", 43 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 44 | }, 45 | { 46 | "ImportPath": "github.com/docker/docker/pkg/units", 47 | "Comment": "v1.2.0-11-g6bc773b", 48 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 49 | }, 50 | { 51 | "ImportPath": "github.com/docker/docker/pkg/version", 52 | "Comment": "v1.2.0-11-g6bc773b", 53 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 54 | }, 55 | { 56 | "ImportPath": "github.com/docker/docker/utils", 57 | "Comment": "v1.2.0-11-g6bc773b", 58 | "Rev": "6bc773b2c1cbce828dde3a5bee7d7d4dd893ec3b" 59 | }, 60 | { 61 | "ImportPath": "github.com/fsouza/go-dockerclient", 62 | "Comment": "0.2.1-219-gadb8617", 63 | "Rev": "adb861704259d548b45e08b5dd7b7c80efcd82e6" 64 | } 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel.go: -------------------------------------------------------------------------------- 1 | package kernel 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | ) 8 | 9 | type KernelVersionInfo struct { 10 | Kernel int 11 | Major int 12 | Minor int 13 | Flavor string 14 | } 15 | 16 | func (k *KernelVersionInfo) String() string { 17 | return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor) 18 | } 19 | 20 | // Compare two KernelVersionInfo struct. 21 | // Returns -1 if a < b, 0 if a == b, 1 it a > b 22 | func CompareKernelVersion(a, b *KernelVersionInfo) int { 23 | if a.Kernel < b.Kernel { 24 | return -1 25 | } else if a.Kernel > b.Kernel { 26 | return 1 27 | } 28 | 29 | if a.Major < b.Major { 30 | return -1 31 | } else if a.Major > b.Major { 32 | return 1 33 | } 34 | 35 | if a.Minor < b.Minor { 36 | return -1 37 | } else if a.Minor > b.Minor { 38 | return 1 39 | } 40 | 41 | return 0 42 | } 43 | 44 | func GetKernelVersion() (*KernelVersionInfo, error) { 45 | var ( 46 | err error 47 | ) 48 | 49 | uts, err := uname() 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | release := make([]byte, len(uts.Release)) 55 | 56 | i := 0 57 | for _, c := range uts.Release { 58 | release[i] = byte(c) 59 | i++ 60 | } 61 | 62 | // Remove the \x00 from the release for Atoi to parse correctly 63 | release = release[:bytes.IndexByte(release, 0)] 64 | 65 | return ParseRelease(string(release)) 66 | } 67 | 68 | func ParseRelease(release string) (*KernelVersionInfo, error) { 69 | var ( 70 | kernel, major, minor, parsed int 71 | flavor, partial string 72 | ) 73 | 74 | // Ignore error from Sscanf to allow an empty flavor. Instead, just 75 | // make sure we got all the version numbers. 76 | parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial) 77 | if parsed < 2 { 78 | return nil, errors.New("Can't parse kernel version " + release) 79 | } 80 | 81 | // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64 82 | parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor) 83 | if parsed < 1 { 84 | flavor = partial 85 | } 86 | 87 | return &KernelVersionInfo{ 88 | Kernel: kernel, 89 | Major: major, 90 | Minor: minor, 91 | Flavor: flavor, 92 | }, nil 93 | } 94 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/opts/opts_test.go: -------------------------------------------------------------------------------- 1 | package opts 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestValidateIPAddress(t *testing.T) { 8 | if ret, err := ValidateIPAddress(`1.2.3.4`); err != nil || ret == "" { 9 | t.Fatalf("ValidateIPAddress(`1.2.3.4`) got %s %s", ret, err) 10 | } 11 | 12 | if ret, err := ValidateIPAddress(`127.0.0.1`); err != nil || ret == "" { 13 | t.Fatalf("ValidateIPAddress(`127.0.0.1`) got %s %s", ret, err) 14 | } 15 | 16 | if ret, err := ValidateIPAddress(`::1`); err != nil || ret == "" { 17 | t.Fatalf("ValidateIPAddress(`::1`) got %s %s", ret, err) 18 | } 19 | 20 | if ret, err := ValidateIPAddress(`127`); err == nil || ret != "" { 21 | t.Fatalf("ValidateIPAddress(`127`) got %s %s", ret, err) 22 | } 23 | 24 | if ret, err := ValidateIPAddress(`random invalid string`); err == nil || ret != "" { 25 | t.Fatalf("ValidateIPAddress(`random invalid string`) got %s %s", ret, err) 26 | } 27 | 28 | } 29 | 30 | func TestListOpts(t *testing.T) { 31 | o := NewListOpts(nil) 32 | o.Set("foo") 33 | o.String() 34 | } 35 | 36 | func TestValidateDnsSearch(t *testing.T) { 37 | valid := []string{ 38 | `.`, 39 | `a`, 40 | `a.`, 41 | `1.foo`, 42 | `17.foo`, 43 | `foo.bar`, 44 | `foo.bar.baz`, 45 | `foo.bar.`, 46 | `foo.bar.baz`, 47 | `foo1.bar2`, 48 | `foo1.bar2.baz`, 49 | `1foo.2bar.`, 50 | `1foo.2bar.baz`, 51 | `foo-1.bar-2`, 52 | `foo-1.bar-2.baz`, 53 | `foo-1.bar-2.`, 54 | `foo-1.bar-2.baz`, 55 | `1-foo.2-bar`, 56 | `1-foo.2-bar.baz`, 57 | `1-foo.2-bar.`, 58 | `1-foo.2-bar.baz`, 59 | } 60 | 61 | invalid := []string{ 62 | ``, 63 | ` `, 64 | ` `, 65 | `17`, 66 | `17.`, 67 | `.17`, 68 | `17-.`, 69 | `17-.foo`, 70 | `.foo`, 71 | `foo-.bar`, 72 | `-foo.bar`, 73 | `foo.bar-`, 74 | `foo.bar-.baz`, 75 | `foo.-bar`, 76 | `foo.-bar.baz`, 77 | } 78 | 79 | for _, domain := range valid { 80 | if ret, err := ValidateDnsSearch(domain); err != nil || ret == "" { 81 | t.Fatalf("ValidateDnsSearch(`"+domain+"`) got %s %s", ret, err) 82 | } 83 | } 84 | 85 | for _, domain := range invalid { 86 | if ret, err := ValidateDnsSearch(domain); err == nil || ret != "" { 87 | t.Fatalf("ValidateDnsSearch(`"+domain+"`) got %s %s", ret, err) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/units/duration_test.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestHumanDuration(t *testing.T) { 9 | // Useful duration abstractions 10 | day := 24 * time.Hour 11 | week := 7 * day 12 | month := 30 * day 13 | year := 365 * day 14 | 15 | assertEquals(t, "Less than a second", HumanDuration(450*time.Millisecond)) 16 | assertEquals(t, "47 seconds", HumanDuration(47*time.Second)) 17 | assertEquals(t, "About a minute", HumanDuration(1*time.Minute)) 18 | assertEquals(t, "3 minutes", HumanDuration(3*time.Minute)) 19 | assertEquals(t, "35 minutes", HumanDuration(35*time.Minute)) 20 | assertEquals(t, "35 minutes", HumanDuration(35*time.Minute+40*time.Second)) 21 | assertEquals(t, "About an hour", HumanDuration(1*time.Hour)) 22 | assertEquals(t, "About an hour", HumanDuration(1*time.Hour+45*time.Minute)) 23 | assertEquals(t, "3 hours", HumanDuration(3*time.Hour)) 24 | assertEquals(t, "3 hours", HumanDuration(3*time.Hour+59*time.Minute)) 25 | assertEquals(t, "4 hours", HumanDuration(3*time.Hour+60*time.Minute)) 26 | assertEquals(t, "24 hours", HumanDuration(24*time.Hour)) 27 | assertEquals(t, "36 hours", HumanDuration(1*day+12*time.Hour)) 28 | assertEquals(t, "2 days", HumanDuration(2*day)) 29 | assertEquals(t, "7 days", HumanDuration(7*day)) 30 | assertEquals(t, "13 days", HumanDuration(13*day+5*time.Hour)) 31 | assertEquals(t, "2 weeks", HumanDuration(2*week)) 32 | assertEquals(t, "2 weeks", HumanDuration(2*week+4*day)) 33 | assertEquals(t, "3 weeks", HumanDuration(3*week)) 34 | assertEquals(t, "4 weeks", HumanDuration(4*week)) 35 | assertEquals(t, "4 weeks", HumanDuration(4*week+3*day)) 36 | assertEquals(t, "4 weeks", HumanDuration(1*month)) 37 | assertEquals(t, "6 weeks", HumanDuration(1*month+2*week)) 38 | assertEquals(t, "8 weeks", HumanDuration(2*month)) 39 | assertEquals(t, "3 months", HumanDuration(3*month+1*week)) 40 | assertEquals(t, "5 months", HumanDuration(5*month+2*week)) 41 | assertEquals(t, "13 months", HumanDuration(13*month)) 42 | assertEquals(t, "23 months", HumanDuration(23*month)) 43 | assertEquals(t, "24 months", HumanDuration(24*month)) 44 | assertEquals(t, "2.010959 years", HumanDuration(24*month+2*week)) 45 | assertEquals(t, "3.164384 years", HumanDuration(3*year+2*month)) 46 | } 47 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/stdcopy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "encoding/binary" 9 | "errors" 10 | "io" 11 | ) 12 | 13 | const ( 14 | stdWriterPrefixLen = 8 15 | stdWriterFdIndex = 0 16 | stdWriterSizeIndex = 4 17 | ) 18 | 19 | var errInvalidStdHeader = errors.New("Unrecognized input header") 20 | 21 | func stdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) { 22 | var ( 23 | buf = make([]byte, 32*1024+stdWriterPrefixLen+1) 24 | bufLen = len(buf) 25 | nr, nw int 26 | er, ew error 27 | out io.Writer 28 | frameSize int 29 | ) 30 | for { 31 | for nr < stdWriterPrefixLen { 32 | var nr2 int 33 | nr2, er = src.Read(buf[nr:]) 34 | if er == io.EOF { 35 | if nr < stdWriterPrefixLen && nr2 < stdWriterPrefixLen { 36 | return written, nil 37 | } 38 | nr += nr2 39 | break 40 | } else if er != nil { 41 | return 0, er 42 | } 43 | nr += nr2 44 | } 45 | switch buf[stdWriterFdIndex] { 46 | case 0: 47 | fallthrough 48 | case 1: 49 | out = dstout 50 | case 2: 51 | out = dsterr 52 | default: 53 | return 0, errInvalidStdHeader 54 | } 55 | frameSize = int(binary.BigEndian.Uint32(buf[stdWriterSizeIndex : stdWriterSizeIndex+4])) 56 | if frameSize+stdWriterPrefixLen > bufLen { 57 | buf = append(buf, make([]byte, frameSize+stdWriterPrefixLen-len(buf)+1)...) 58 | bufLen = len(buf) 59 | } 60 | for nr < frameSize+stdWriterPrefixLen { 61 | var nr2 int 62 | nr2, er = src.Read(buf[nr:]) 63 | if er == io.EOF { 64 | if nr == 0 { 65 | return written, nil 66 | } 67 | nr += nr2 68 | break 69 | } else if er != nil { 70 | return 0, er 71 | } 72 | nr += nr2 73 | } 74 | bound := frameSize + stdWriterPrefixLen 75 | if bound > nr { 76 | bound = nr 77 | } 78 | nw, ew = out.Write(buf[stdWriterPrefixLen:bound]) 79 | if nw > 0 { 80 | written += int64(nw) 81 | } 82 | if ew != nil { 83 | return 0, ew 84 | } 85 | if nw != frameSize { 86 | return written, io.ErrShortWrite 87 | } 88 | copy(buf, buf[frameSize+stdWriterPrefixLen:]) 89 | nr -= frameSize + stdWriterPrefixLen 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/units/size.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | // See: http://en.wikipedia.org/wiki/Binary_prefix 11 | const ( 12 | // Decimal 13 | KB = 1000 14 | MB = 1000 * KB 15 | GB = 1000 * MB 16 | TB = 1000 * GB 17 | PB = 1000 * TB 18 | 19 | // Binary 20 | KiB = 1024 21 | MiB = 1024 * KiB 22 | GiB = 1024 * MiB 23 | TiB = 1024 * GiB 24 | PiB = 1024 * TiB 25 | ) 26 | 27 | type unitMap map[string]int64 28 | 29 | var ( 30 | decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB} 31 | binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB} 32 | ) 33 | 34 | var sizeRegex *regexp.Regexp 35 | 36 | func init() { 37 | sizeRegex = regexp.MustCompile("^(\\d+)([kKmMgGtTpP])?[bB]?$") 38 | } 39 | 40 | var unitAbbrs = [...]string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} 41 | 42 | // HumanSize returns a human-readable approximation of a size 43 | // using SI standard (eg. "44kB", "17MB") 44 | func HumanSize(size int64) string { 45 | i := 0 46 | sizef := float64(size) 47 | for sizef >= 1000.0 { 48 | sizef = sizef / 1000.0 49 | i++ 50 | } 51 | return fmt.Sprintf("%.4g %s", sizef, unitAbbrs[i]) 52 | } 53 | 54 | // FromHumanSize returns an integer from a human-readable specification of a 55 | // size using SI standard (eg. "44kB", "17MB") 56 | func FromHumanSize(size string) (int64, error) { 57 | return parseSize(size, decimalMap) 58 | } 59 | 60 | // Parses a human-readable string representing an amount of RAM 61 | // in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and 62 | // returns the number of bytes, or -1 if the string is unparseable. 63 | // Units are case-insensitive, and the 'b' suffix is optional. 64 | func RAMInBytes(size string) (int64, error) { 65 | return parseSize(size, binaryMap) 66 | } 67 | 68 | // Parses the human-readable size string into the amount it represents 69 | func parseSize(sizeStr string, uMap unitMap) (int64, error) { 70 | matches := sizeRegex.FindStringSubmatch(sizeStr) 71 | if len(matches) != 3 { 72 | return -1, fmt.Errorf("Invalid size: '%s'", sizeStr) 73 | } 74 | 75 | size, err := strconv.ParseInt(matches[1], 10, 0) 76 | if err != nil { 77 | return -1, err 78 | } 79 | 80 | unitPrefix := strings.ToLower(matches[2]) 81 | if mul, ok := uMap[unitPrefix]; ok { 82 | size *= mul 83 | } 84 | 85 | return size, nil 86 | } 87 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/shutdown_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestShutdownEmpty(t *testing.T) { 9 | eng := New() 10 | if eng.IsShutdown() { 11 | t.Fatalf("IsShutdown should be false") 12 | } 13 | eng.Shutdown() 14 | if !eng.IsShutdown() { 15 | t.Fatalf("IsShutdown should be true") 16 | } 17 | } 18 | 19 | func TestShutdownAfterRun(t *testing.T) { 20 | eng := New() 21 | var called bool 22 | eng.Register("foo", func(job *Job) Status { 23 | called = true 24 | return StatusOK 25 | }) 26 | if err := eng.Job("foo").Run(); err != nil { 27 | t.Fatal(err) 28 | } 29 | eng.Shutdown() 30 | if err := eng.Job("foo").Run(); err == nil { 31 | t.Fatalf("%#v", *eng) 32 | } 33 | } 34 | 35 | // An approximate and racy, but better-than-nothing test that 36 | // 37 | func TestShutdownDuringRun(t *testing.T) { 38 | var ( 39 | jobDelay time.Duration = 500 * time.Millisecond 40 | jobDelayLow time.Duration = 100 * time.Millisecond 41 | jobDelayHigh time.Duration = 700 * time.Millisecond 42 | ) 43 | eng := New() 44 | var completed bool 45 | eng.Register("foo", func(job *Job) Status { 46 | time.Sleep(jobDelay) 47 | completed = true 48 | return StatusOK 49 | }) 50 | go eng.Job("foo").Run() 51 | time.Sleep(50 * time.Millisecond) 52 | done := make(chan struct{}) 53 | var startShutdown time.Time 54 | go func() { 55 | startShutdown = time.Now() 56 | eng.Shutdown() 57 | close(done) 58 | }() 59 | time.Sleep(50 * time.Millisecond) 60 | if err := eng.Job("foo").Run(); err == nil { 61 | t.Fatalf("run on shutdown should fail: %#v", *eng) 62 | } 63 | <-done 64 | // Verify that Shutdown() blocks for roughly 500ms, instead 65 | // of returning almost instantly. 66 | // 67 | // We use >100ms to leave ample margin for race conditions between 68 | // goroutines. It's possible (but unlikely in reasonable testing 69 | // conditions), that this test will cause a false positive or false 70 | // negative. But it's probably better than not having any test 71 | // for the 99.999% of time where testing conditions are reasonable. 72 | if d := time.Since(startShutdown); d.Nanoseconds() < jobDelayLow.Nanoseconds() { 73 | t.Fatalf("shutdown did not block long enough: %v", d) 74 | } else if d.Nanoseconds() > jobDelayHigh.Nanoseconds() { 75 | t.Fatalf("shutdown blocked too long: %v", d) 76 | } 77 | if !completed { 78 | t.Fatalf("job did not complete") 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/job_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestJobStatusOK(t *testing.T) { 10 | eng := New() 11 | eng.Register("return_ok", func(job *Job) Status { return StatusOK }) 12 | err := eng.Job("return_ok").Run() 13 | if err != nil { 14 | t.Fatalf("Expected: err=%v\nReceived: err=%v", nil, err) 15 | } 16 | } 17 | 18 | func TestJobStatusErr(t *testing.T) { 19 | eng := New() 20 | eng.Register("return_err", func(job *Job) Status { return StatusErr }) 21 | err := eng.Job("return_err").Run() 22 | if err == nil { 23 | t.Fatalf("When a job returns StatusErr, Run() should return an error") 24 | } 25 | } 26 | 27 | func TestJobStatusNotFound(t *testing.T) { 28 | eng := New() 29 | eng.Register("return_not_found", func(job *Job) Status { return StatusNotFound }) 30 | err := eng.Job("return_not_found").Run() 31 | if err == nil { 32 | t.Fatalf("When a job returns StatusNotFound, Run() should return an error") 33 | } 34 | } 35 | 36 | func TestJobStdoutString(t *testing.T) { 37 | eng := New() 38 | // FIXME: test multiple combinations of output and status 39 | eng.Register("say_something_in_stdout", func(job *Job) Status { 40 | job.Printf("Hello world\n") 41 | return StatusOK 42 | }) 43 | 44 | job := eng.Job("say_something_in_stdout") 45 | var outputBuffer = bytes.NewBuffer(nil) 46 | job.Stdout.Add(outputBuffer) 47 | if err := job.Run(); err != nil { 48 | t.Fatal(err) 49 | } 50 | fmt.Println(outputBuffer) 51 | var output = Tail(outputBuffer, 1) 52 | if expectedOutput := "Hello world"; output != expectedOutput { 53 | t.Fatalf("Stdout last line:\nExpected: %v\nReceived: %v", expectedOutput, output) 54 | } 55 | } 56 | 57 | func TestJobStderrString(t *testing.T) { 58 | eng := New() 59 | // FIXME: test multiple combinations of output and status 60 | eng.Register("say_something_in_stderr", func(job *Job) Status { 61 | job.Errorf("Warning, something might happen\nHere it comes!\nOh no...\nSomething happened\n") 62 | return StatusOK 63 | }) 64 | 65 | job := eng.Job("say_something_in_stderr") 66 | var outputBuffer = bytes.NewBuffer(nil) 67 | job.Stderr.Add(outputBuffer) 68 | if err := job.Run(); err != nil { 69 | t.Fatal(err) 70 | } 71 | var output = Tail(outputBuffer, 1) 72 | if expectedOutput := "Something happened"; output != expectedOutput { 73 | t.Fatalf("Stderr last line:\nExpected: %v\nReceived: %v", expectedOutput, output) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel_test.go: -------------------------------------------------------------------------------- 1 | package kernel 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) { 8 | var ( 9 | a *KernelVersionInfo 10 | ) 11 | a, _ = ParseRelease(release) 12 | 13 | if r := CompareKernelVersion(a, b); r != result { 14 | t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result) 15 | } 16 | if a.Flavor != b.Flavor { 17 | t.Fatalf("Unexpected parsed kernel flavor. Found %s, expected %s", a.Flavor, b.Flavor) 18 | } 19 | } 20 | 21 | func TestParseRelease(t *testing.T) { 22 | assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0) 23 | assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0) 24 | assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0) 25 | assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0) 26 | assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0) 27 | assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0) 28 | } 29 | 30 | func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) { 31 | if r := CompareKernelVersion(a, b); r != result { 32 | t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result) 33 | } 34 | } 35 | 36 | func TestCompareKernelVersion(t *testing.T) { 37 | assertKernelVersion(t, 38 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 39 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 40 | 0) 41 | assertKernelVersion(t, 42 | &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0}, 43 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 44 | -1) 45 | assertKernelVersion(t, 46 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 47 | &KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0}, 48 | 1) 49 | assertKernelVersion(t, 50 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 51 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 52 | 0) 53 | assertKernelVersion(t, 54 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5}, 55 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 56 | 1) 57 | assertKernelVersion(t, 58 | &KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20}, 59 | &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 60 | -1) 61 | } 62 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/dockerfile.tar: -------------------------------------------------------------------------------- 1 | Dockerfile000644 000766 000024 00000001225 12327754570 013535 0ustar00tarsisstaff000000 000000 # this file describes how to build tsuru python image 2 | # to run it: 3 | # 1- install docker 4 | # 2- run: $ docker build -t tsuru/python https://raw.github.com/tsuru/basebuilder/master/python/Dockerfile 5 | 6 | from base:ubuntu-quantal 7 | run apt-get install wget -y --force-yes 8 | run wget http://github.com/tsuru/basebuilder/tarball/master -O basebuilder.tar.gz --no-check-certificate 9 | run mkdir /var/lib/tsuru 10 | run tar -xvf basebuilder.tar.gz -C /var/lib/tsuru --strip 1 11 | run cp /var/lib/tsuru/python/deploy /var/lib/tsuru 12 | run cp /var/lib/tsuru/base/restart /var/lib/tsuru 13 | run cp /var/lib/tsuru/base/start /var/lib/tsuru 14 | run /var/lib/tsuru/base/install 15 | run /var/lib/tsuru/base/setup 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/table_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "testing" 7 | ) 8 | 9 | func TestTableWriteTo(t *testing.T) { 10 | table := NewTable("", 0) 11 | e := &Env{} 12 | e.Set("foo", "bar") 13 | table.Add(e) 14 | var buf bytes.Buffer 15 | if _, err := table.WriteTo(&buf); err != nil { 16 | t.Fatal(err) 17 | } 18 | output := make(map[string]string) 19 | if err := json.Unmarshal(buf.Bytes(), &output); err != nil { 20 | t.Fatal(err) 21 | } 22 | if len(output) != 1 { 23 | t.Fatalf("Incorrect output: %v", output) 24 | } 25 | if val, exists := output["foo"]; !exists || val != "bar" { 26 | t.Fatalf("Inccorect output: %v", output) 27 | } 28 | } 29 | 30 | func TestTableSortStringValue(t *testing.T) { 31 | table := NewTable("Key", 0) 32 | 33 | e := &Env{} 34 | e.Set("Key", "A") 35 | table.Add(e) 36 | 37 | e = &Env{} 38 | e.Set("Key", "D") 39 | table.Add(e) 40 | 41 | e = &Env{} 42 | e.Set("Key", "B") 43 | table.Add(e) 44 | 45 | e = &Env{} 46 | e.Set("Key", "C") 47 | table.Add(e) 48 | 49 | table.Sort() 50 | 51 | if len := table.Len(); len != 4 { 52 | t.Fatalf("Expected 4, got %d", len) 53 | } 54 | 55 | if value := table.Data[0].Get("Key"); value != "A" { 56 | t.Fatalf("Expected A, got %s", value) 57 | } 58 | 59 | if value := table.Data[1].Get("Key"); value != "B" { 60 | t.Fatalf("Expected B, got %s", value) 61 | } 62 | 63 | if value := table.Data[2].Get("Key"); value != "C" { 64 | t.Fatalf("Expected C, got %s", value) 65 | } 66 | 67 | if value := table.Data[3].Get("Key"); value != "D" { 68 | t.Fatalf("Expected D, got %s", value) 69 | } 70 | } 71 | 72 | func TestTableReverseSortStringValue(t *testing.T) { 73 | table := NewTable("Key", 0) 74 | 75 | e := &Env{} 76 | e.Set("Key", "A") 77 | table.Add(e) 78 | 79 | e = &Env{} 80 | e.Set("Key", "D") 81 | table.Add(e) 82 | 83 | e = &Env{} 84 | e.Set("Key", "B") 85 | table.Add(e) 86 | 87 | e = &Env{} 88 | e.Set("Key", "C") 89 | table.Add(e) 90 | 91 | table.ReverseSort() 92 | 93 | if len := table.Len(); len != 4 { 94 | t.Fatalf("Expected 4, got %d", len) 95 | } 96 | 97 | if value := table.Data[0].Get("Key"); value != "D" { 98 | t.Fatalf("Expected D, got %s", value) 99 | } 100 | 101 | if value := table.Data[1].Get("Key"); value != "C" { 102 | t.Fatalf("Expected B, got %s", value) 103 | } 104 | 105 | if value := table.Data[2].Get("Key"); value != "B" { 106 | t.Fatalf("Expected C, got %s", value) 107 | } 108 | 109 | if value := table.Data[3].Get("Key"); value != "A" { 110 | t.Fatalf("Expected A, got %s", value) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "net/http" 11 | "net/http/httptest" 12 | "strings" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | func TestEventListeners(t *testing.T) { 18 | response := `{"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924} 19 | {"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924} 20 | {"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966} 21 | {"status":"destroy","id":"dfdf82bd3881","from":"base:latest","time":1374067970} 22 | ` 23 | 24 | var req http.Request 25 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 26 | rsc := bufio.NewScanner(strings.NewReader(response)) 27 | for rsc.Scan() { 28 | w.Write([]byte(rsc.Text())) 29 | w.(http.Flusher).Flush() 30 | time.Sleep(10 * time.Millisecond) 31 | } 32 | req = *r 33 | })) 34 | defer server.Close() 35 | 36 | client, err := NewClient(server.URL) 37 | if err != nil { 38 | t.Errorf("Failed to create client: %s", err) 39 | } 40 | client.SkipServerVersionCheck = true 41 | 42 | listener := make(chan *APIEvents, 10) 43 | defer func() { time.Sleep(10 * time.Millisecond); client.RemoveEventListener(listener) }() 44 | 45 | err = client.AddEventListener(listener) 46 | if err != nil { 47 | t.Errorf("Failed to add event listener: %s", err) 48 | } 49 | 50 | timeout := time.After(1 * time.Second) 51 | var count int 52 | 53 | for { 54 | select { 55 | case msg := <-listener: 56 | t.Logf("Recieved: %s", *msg) 57 | count++ 58 | err = checkEvent(count, msg) 59 | if err != nil { 60 | t.Fatalf("Check event failed: %s", err) 61 | } 62 | if count == 4 { 63 | return 64 | } 65 | case <-timeout: 66 | t.Fatal("TestAddEventListener timed out waiting on events") 67 | } 68 | } 69 | } 70 | 71 | func checkEvent(index int, event *APIEvents) error { 72 | if event.ID != "dfdf82bd3881" { 73 | return fmt.Errorf("event ID did not match. Expected dfdf82bd3881 got %s", event.ID) 74 | } 75 | if event.From != "base:latest" { 76 | return fmt.Errorf("event from did not match. Expected base:latest got %s", event.From) 77 | } 78 | var status string 79 | switch index { 80 | case 1: 81 | status = "create" 82 | case 2: 83 | status = "start" 84 | case 3: 85 | status = "stop" 86 | case 4: 87 | status = "destroy" 88 | } 89 | if event.Status != status { 90 | return fmt.Errorf("event status did not match. Expected %s got %s", status, event.Status) 91 | } 92 | return nil 93 | } 94 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/term/term.go: -------------------------------------------------------------------------------- 1 | package term 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | var ( 12 | ErrInvalidState = errors.New("Invalid terminal state") 13 | ) 14 | 15 | type State struct { 16 | termios Termios 17 | } 18 | 19 | type Winsize struct { 20 | Height uint16 21 | Width uint16 22 | x uint16 23 | y uint16 24 | } 25 | 26 | func GetWinsize(fd uintptr) (*Winsize, error) { 27 | ws := &Winsize{} 28 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws))) 29 | // Skipp errno = 0 30 | if err == 0 { 31 | return ws, nil 32 | } 33 | return ws, err 34 | } 35 | 36 | func SetWinsize(fd uintptr, ws *Winsize) error { 37 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) 38 | // Skipp errno = 0 39 | if err == 0 { 40 | return nil 41 | } 42 | return err 43 | } 44 | 45 | // IsTerminal returns true if the given file descriptor is a terminal. 46 | func IsTerminal(fd uintptr) bool { 47 | var termios Termios 48 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) 49 | return err == 0 50 | } 51 | 52 | // Restore restores the terminal connected to the given file descriptor to a 53 | // previous state. 54 | func RestoreTerminal(fd uintptr, state *State) error { 55 | if state == nil { 56 | return ErrInvalidState 57 | } 58 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) 59 | if err != 0 { 60 | return err 61 | } 62 | return nil 63 | } 64 | 65 | func SaveState(fd uintptr) (*State, error) { 66 | var oldState State 67 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 68 | return nil, err 69 | } 70 | 71 | return &oldState, nil 72 | } 73 | 74 | func DisableEcho(fd uintptr, state *State) error { 75 | newState := state.termios 76 | newState.Lflag &^= syscall.ECHO 77 | 78 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { 79 | return err 80 | } 81 | handleInterrupt(fd, state) 82 | return nil 83 | } 84 | 85 | func SetRawTerminal(fd uintptr) (*State, error) { 86 | oldState, err := MakeRaw(fd) 87 | if err != nil { 88 | return nil, err 89 | } 90 | handleInterrupt(fd, oldState) 91 | return oldState, err 92 | } 93 | 94 | func handleInterrupt(fd uintptr, state *State) { 95 | sigchan := make(chan os.Signal, 1) 96 | signal.Notify(sigchan, os.Interrupt) 97 | 98 | go func() { 99 | _ = <-sigchan 100 | RestoreTerminal(fd, state) 101 | os.Exit(0) 102 | }() 103 | } 104 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "os" 9 | "reflect" 10 | "strings" 11 | "text/template" 12 | 13 | flag "github.com/docker/docker/pkg/mflag" 14 | "github.com/docker/docker/pkg/term" 15 | "github.com/docker/docker/registry" 16 | ) 17 | 18 | type DockerCli struct { 19 | proto string 20 | addr string 21 | configFile *registry.ConfigFile 22 | in io.ReadCloser 23 | out io.Writer 24 | err io.Writer 25 | isTerminal bool 26 | terminalFd uintptr 27 | tlsConfig *tls.Config 28 | scheme string 29 | } 30 | 31 | var funcMap = template.FuncMap{ 32 | "json": func(v interface{}) string { 33 | a, _ := json.Marshal(v) 34 | return string(a) 35 | }, 36 | } 37 | 38 | func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) { 39 | if len(name) == 0 { 40 | return nil, false 41 | } 42 | methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) 43 | method := reflect.ValueOf(cli).MethodByName(methodName) 44 | if !method.IsValid() { 45 | return nil, false 46 | } 47 | return method.Interface().(func(...string) error), true 48 | } 49 | 50 | // Cmd executes the specified command 51 | func (cli *DockerCli) Cmd(args ...string) error { 52 | if len(args) > 0 { 53 | method, exists := cli.getMethod(args[0]) 54 | if !exists { 55 | fmt.Println("Error: Command not found:", args[0]) 56 | return cli.CmdHelp(args[1:]...) 57 | } 58 | return method(args[1:]...) 59 | } 60 | return cli.CmdHelp(args...) 61 | } 62 | 63 | func (cli *DockerCli) Subcmd(name, signature, description string) *flag.FlagSet { 64 | flags := flag.NewFlagSet(name, flag.ContinueOnError) 65 | flags.Usage = func() { 66 | fmt.Fprintf(cli.err, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description) 67 | flags.PrintDefaults() 68 | os.Exit(2) 69 | } 70 | return flags 71 | } 72 | 73 | func (cli *DockerCli) LoadConfigFile() (err error) { 74 | cli.configFile, err = registry.LoadConfig(os.Getenv("HOME")) 75 | if err != nil { 76 | fmt.Fprintf(cli.err, "WARNING: %s\n", err) 77 | } 78 | return err 79 | } 80 | 81 | func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli { 82 | var ( 83 | isTerminal = false 84 | terminalFd uintptr 85 | scheme = "http" 86 | ) 87 | 88 | if tlsConfig != nil { 89 | scheme = "https" 90 | } 91 | 92 | if in != nil { 93 | if file, ok := out.(*os.File); ok { 94 | terminalFd = file.Fd() 95 | isTerminal = term.IsTerminal(terminalFd) 96 | } 97 | } 98 | 99 | if err == nil { 100 | err = out 101 | } 102 | return &DockerCli{ 103 | proto: proto, 104 | addr: addr, 105 | in: in, 106 | out: out, 107 | err: err, 108 | isTerminal: isTerminal, 109 | terminalFd: terminalFd, 110 | tlsConfig: tlsConfig, 111 | scheme: scheme, 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/streamformatter.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | type StreamFormatter struct { 10 | json bool 11 | } 12 | 13 | func NewStreamFormatter(json bool) *StreamFormatter { 14 | return &StreamFormatter{json} 15 | } 16 | 17 | const streamNewline = "\r\n" 18 | 19 | var streamNewlineBytes = []byte(streamNewline) 20 | 21 | func (sf *StreamFormatter) FormatStream(str string) []byte { 22 | if sf.json { 23 | b, err := json.Marshal(&JSONMessage{Stream: str}) 24 | if err != nil { 25 | return sf.FormatError(err) 26 | } 27 | return append(b, streamNewlineBytes...) 28 | } 29 | return []byte(str + "\r") 30 | } 31 | 32 | func (sf *StreamFormatter) FormatStatus(id, format string, a ...interface{}) []byte { 33 | str := fmt.Sprintf(format, a...) 34 | if sf.json { 35 | b, err := json.Marshal(&JSONMessage{ID: id, Status: str}) 36 | if err != nil { 37 | return sf.FormatError(err) 38 | } 39 | return append(b, streamNewlineBytes...) 40 | } 41 | return []byte(str + streamNewline) 42 | } 43 | 44 | func (sf *StreamFormatter) FormatError(err error) []byte { 45 | if sf.json { 46 | jsonError, ok := err.(*JSONError) 47 | if !ok { 48 | jsonError = &JSONError{Message: err.Error()} 49 | } 50 | if b, err := json.Marshal(&JSONMessage{Error: jsonError, ErrorMessage: err.Error()}); err == nil { 51 | return append(b, streamNewlineBytes...) 52 | } 53 | return []byte("{\"error\":\"format error\"}" + streamNewline) 54 | } 55 | return []byte("Error: " + err.Error() + streamNewline) 56 | } 57 | 58 | func (sf *StreamFormatter) FormatProgress(id, action string, progress *JSONProgress) []byte { 59 | if progress == nil { 60 | progress = &JSONProgress{} 61 | } 62 | if sf.json { 63 | 64 | b, err := json.Marshal(&JSONMessage{ 65 | Status: action, 66 | ProgressMessage: progress.String(), 67 | Progress: progress, 68 | ID: id, 69 | }) 70 | if err != nil { 71 | return nil 72 | } 73 | return b 74 | } 75 | endl := "\r" 76 | if progress.String() == "" { 77 | endl += "\n" 78 | } 79 | return []byte(action + " " + progress.String() + endl) 80 | } 81 | 82 | func (sf *StreamFormatter) Json() bool { 83 | return sf.json 84 | } 85 | 86 | type StdoutFormater struct { 87 | io.Writer 88 | *StreamFormatter 89 | } 90 | 91 | func (sf *StdoutFormater) Write(buf []byte) (int, error) { 92 | formattedBuf := sf.StreamFormatter.FormatStream(string(buf)) 93 | n, err := sf.Writer.Write(formattedBuf) 94 | if n != len(formattedBuf) { 95 | return n, io.ErrShortWrite 96 | } 97 | return len(buf), err 98 | } 99 | 100 | type StderrFormater struct { 101 | io.Writer 102 | *StreamFormatter 103 | } 104 | 105 | func (sf *StderrFormater) Write(buf []byte) (int, error) { 106 | formattedBuf := sf.StreamFormatter.FormatStream("\033[91m" + string(buf) + "\033[0m") 107 | n, err := sf.Writer.Write(formattedBuf) 108 | if n != len(formattedBuf) { 109 | return n, io.ErrShortWrite 110 | } 111 | return len(buf), err 112 | } 113 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/table.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io" 7 | "sort" 8 | "strconv" 9 | ) 10 | 11 | type Table struct { 12 | Data []*Env 13 | sortKey string 14 | Chan chan *Env 15 | } 16 | 17 | func NewTable(sortKey string, sizeHint int) *Table { 18 | return &Table{ 19 | make([]*Env, 0, sizeHint), 20 | sortKey, 21 | make(chan *Env), 22 | } 23 | } 24 | 25 | func (t *Table) SetKey(sortKey string) { 26 | t.sortKey = sortKey 27 | } 28 | 29 | func (t *Table) Add(env *Env) { 30 | t.Data = append(t.Data, env) 31 | } 32 | 33 | func (t *Table) Len() int { 34 | return len(t.Data) 35 | } 36 | 37 | func (t *Table) Less(a, b int) bool { 38 | return t.lessBy(a, b, t.sortKey) 39 | } 40 | 41 | func (t *Table) lessBy(a, b int, by string) bool { 42 | keyA := t.Data[a].Get(by) 43 | keyB := t.Data[b].Get(by) 44 | intA, errA := strconv.ParseInt(keyA, 10, 64) 45 | intB, errB := strconv.ParseInt(keyB, 10, 64) 46 | if errA == nil && errB == nil { 47 | return intA < intB 48 | } 49 | return keyA < keyB 50 | } 51 | 52 | func (t *Table) Swap(a, b int) { 53 | tmp := t.Data[a] 54 | t.Data[a] = t.Data[b] 55 | t.Data[b] = tmp 56 | } 57 | 58 | func (t *Table) Sort() { 59 | sort.Sort(t) 60 | } 61 | 62 | func (t *Table) ReverseSort() { 63 | sort.Sort(sort.Reverse(t)) 64 | } 65 | 66 | func (t *Table) WriteListTo(dst io.Writer) (n int64, err error) { 67 | if _, err := dst.Write([]byte{'['}); err != nil { 68 | return -1, err 69 | } 70 | n = 1 71 | for i, env := range t.Data { 72 | bytes, err := env.WriteTo(dst) 73 | if err != nil { 74 | return -1, err 75 | } 76 | n += bytes 77 | if i != len(t.Data)-1 { 78 | if _, err := dst.Write([]byte{','}); err != nil { 79 | return -1, err 80 | } 81 | n += 1 82 | } 83 | } 84 | if _, err := dst.Write([]byte{']'}); err != nil { 85 | return -1, err 86 | } 87 | return n + 1, nil 88 | } 89 | 90 | func (t *Table) ToListString() (string, error) { 91 | buffer := bytes.NewBuffer(nil) 92 | if _, err := t.WriteListTo(buffer); err != nil { 93 | return "", err 94 | } 95 | return buffer.String(), nil 96 | } 97 | 98 | func (t *Table) WriteTo(dst io.Writer) (n int64, err error) { 99 | for _, env := range t.Data { 100 | bytes, err := env.WriteTo(dst) 101 | if err != nil { 102 | return -1, err 103 | } 104 | n += bytes 105 | } 106 | return n, nil 107 | } 108 | 109 | func (t *Table) ReadListFrom(src []byte) (n int64, err error) { 110 | var array []interface{} 111 | 112 | if err := json.Unmarshal(src, &array); err != nil { 113 | return -1, err 114 | } 115 | 116 | for _, item := range array { 117 | if m, ok := item.(map[string]interface{}); ok { 118 | env := &Env{} 119 | for key, value := range m { 120 | env.SetAuto(key, value) 121 | } 122 | t.Add(env) 123 | } 124 | } 125 | 126 | return int64(len(src)), nil 127 | } 128 | 129 | func (t *Table) ReadFrom(src io.Reader) (n int64, err error) { 130 | decoder := NewDecoder(src) 131 | for { 132 | env, err := decoder.Decode() 133 | if err == io.EOF { 134 | return 0, nil 135 | } else if err != nil { 136 | return -1, err 137 | } 138 | t.Add(env) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers.go: -------------------------------------------------------------------------------- 1 | package parsers 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | // FIXME: Change this not to receive default value as parameter 10 | func ParseHost(defaultHost string, defaultUnix, addr string) (string, error) { 11 | var ( 12 | proto string 13 | host string 14 | port int 15 | ) 16 | addr = strings.TrimSpace(addr) 17 | switch { 18 | case addr == "tcp://": 19 | return "", fmt.Errorf("Invalid bind address format: %s", addr) 20 | case strings.HasPrefix(addr, "unix://"): 21 | proto = "unix" 22 | addr = strings.TrimPrefix(addr, "unix://") 23 | if addr == "" { 24 | addr = defaultUnix 25 | } 26 | case strings.HasPrefix(addr, "tcp://"): 27 | proto = "tcp" 28 | addr = strings.TrimPrefix(addr, "tcp://") 29 | case strings.HasPrefix(addr, "fd://"): 30 | return addr, nil 31 | case addr == "": 32 | proto = "unix" 33 | addr = defaultUnix 34 | default: 35 | if strings.Contains(addr, "://") { 36 | return "", fmt.Errorf("Invalid bind address protocol: %s", addr) 37 | } 38 | proto = "tcp" 39 | } 40 | 41 | if proto != "unix" && strings.Contains(addr, ":") { 42 | hostParts := strings.Split(addr, ":") 43 | if len(hostParts) != 2 { 44 | return "", fmt.Errorf("Invalid bind address format: %s", addr) 45 | } 46 | if hostParts[0] != "" { 47 | host = hostParts[0] 48 | } else { 49 | host = defaultHost 50 | } 51 | 52 | if p, err := strconv.Atoi(hostParts[1]); err == nil && p != 0 { 53 | port = p 54 | } else { 55 | return "", fmt.Errorf("Invalid bind address format: %s", addr) 56 | } 57 | 58 | } else if proto == "tcp" && !strings.Contains(addr, ":") { 59 | return "", fmt.Errorf("Invalid bind address format: %s", addr) 60 | } else { 61 | host = addr 62 | } 63 | if proto == "unix" { 64 | return fmt.Sprintf("%s://%s", proto, host), nil 65 | } 66 | return fmt.Sprintf("%s://%s:%d", proto, host, port), nil 67 | } 68 | 69 | // Get a repos name and returns the right reposName + tag 70 | // The tag can be confusing because of a port in a repository name. 71 | // Ex: localhost.localdomain:5000/samalba/hipache:latest 72 | func ParseRepositoryTag(repos string) (string, string) { 73 | n := strings.LastIndex(repos, ":") 74 | if n < 0 { 75 | return repos, "" 76 | } 77 | if tag := repos[n+1:]; !strings.Contains(tag, "/") { 78 | return repos[:n], tag 79 | } 80 | return repos, "" 81 | } 82 | 83 | func PartParser(template, data string) (map[string]string, error) { 84 | // ip:public:private 85 | var ( 86 | templateParts = strings.Split(template, ":") 87 | parts = strings.Split(data, ":") 88 | out = make(map[string]string, len(templateParts)) 89 | ) 90 | if len(parts) != len(templateParts) { 91 | return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template) 92 | } 93 | 94 | for i, t := range templateParts { 95 | value := "" 96 | if len(parts) > i { 97 | value = parts[i] 98 | } 99 | out[t] = value 100 | } 101 | return out, nil 102 | } 103 | 104 | func ParseKeyValueOpt(opt string) (string, string, error) { 105 | parts := strings.SplitN(opt, "=", 2) 106 | if len(parts) != 2 { 107 | return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt) 108 | } 109 | return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil 110 | } 111 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/units/size_test.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | import ( 4 | "reflect" 5 | "runtime" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func TestHumanSize(t *testing.T) { 11 | assertEquals(t, "1 kB", HumanSize(1000)) 12 | assertEquals(t, "1.024 kB", HumanSize(1024)) 13 | assertEquals(t, "1 MB", HumanSize(1000000)) 14 | assertEquals(t, "1.049 MB", HumanSize(1048576)) 15 | assertEquals(t, "2 MB", HumanSize(2*MB)) 16 | assertEquals(t, "3.42 GB", HumanSize(3.42*GB)) 17 | assertEquals(t, "5.372 TB", HumanSize(5.372*TB)) 18 | assertEquals(t, "2.22 PB", HumanSize(2.22*PB)) 19 | } 20 | 21 | func TestFromHumanSize(t *testing.T) { 22 | assertSuccessEquals(t, 32, FromHumanSize, "32") 23 | assertSuccessEquals(t, 32, FromHumanSize, "32b") 24 | assertSuccessEquals(t, 32, FromHumanSize, "32B") 25 | assertSuccessEquals(t, 32*KB, FromHumanSize, "32k") 26 | assertSuccessEquals(t, 32*KB, FromHumanSize, "32K") 27 | assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb") 28 | assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb") 29 | assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb") 30 | assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb") 31 | assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb") 32 | assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb") 33 | 34 | assertError(t, FromHumanSize, "") 35 | assertError(t, FromHumanSize, "hello") 36 | assertError(t, FromHumanSize, "-32") 37 | assertError(t, FromHumanSize, "32.3") 38 | assertError(t, FromHumanSize, " 32 ") 39 | assertError(t, FromHumanSize, "32.3Kb") 40 | assertError(t, FromHumanSize, "32 mb") 41 | assertError(t, FromHumanSize, "32m b") 42 | assertError(t, FromHumanSize, "32bm") 43 | } 44 | 45 | func TestRAMInBytes(t *testing.T) { 46 | assertSuccessEquals(t, 32, RAMInBytes, "32") 47 | assertSuccessEquals(t, 32, RAMInBytes, "32b") 48 | assertSuccessEquals(t, 32, RAMInBytes, "32B") 49 | assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k") 50 | assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K") 51 | assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb") 52 | assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb") 53 | assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb") 54 | assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb") 55 | assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb") 56 | assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb") 57 | assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB") 58 | assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P") 59 | 60 | assertError(t, RAMInBytes, "") 61 | assertError(t, RAMInBytes, "hello") 62 | assertError(t, RAMInBytes, "-32") 63 | assertError(t, RAMInBytes, "32.3") 64 | assertError(t, RAMInBytes, " 32 ") 65 | assertError(t, RAMInBytes, "32.3Kb") 66 | assertError(t, RAMInBytes, "32 mb") 67 | assertError(t, RAMInBytes, "32m b") 68 | assertError(t, RAMInBytes, "32bm") 69 | } 70 | 71 | func assertEquals(t *testing.T, expected, actual interface{}) { 72 | if expected != actual { 73 | t.Errorf("Expected '%v' but got '%v'", expected, actual) 74 | } 75 | } 76 | 77 | // func that maps to the parse function signatures as testing abstraction 78 | type parseFn func(string) (int64, error) 79 | 80 | // Define 'String()' for pretty-print 81 | func (fn parseFn) String() string { 82 | fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() 83 | return fnName[strings.LastIndex(fnName, ".")+1:] 84 | } 85 | 86 | func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) { 87 | res, err := fn(arg) 88 | if err != nil || res != expected { 89 | t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err) 90 | } 91 | } 92 | 93 | func assertError(t *testing.T, fn parseFn, arg string) { 94 | res, err := fn(arg) 95 | if err == nil && res != -1 { 96 | t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/operatingsystem/operatingsystem_test.go: -------------------------------------------------------------------------------- 1 | package operatingsystem 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | func TestGetOperatingSystem(t *testing.T) { 11 | var ( 12 | backup = etcOsRelease 13 | ubuntuTrusty = []byte(`NAME="Ubuntu" 14 | VERSION="14.04, Trusty Tahr" 15 | ID=ubuntu 16 | ID_LIKE=debian 17 | PRETTY_NAME="Ubuntu 14.04 LTS" 18 | VERSION_ID="14.04" 19 | HOME_URL="http://www.ubuntu.com/" 20 | SUPPORT_URL="http://help.ubuntu.com/" 21 | BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`) 22 | gentoo = []byte(`NAME=Gentoo 23 | ID=gentoo 24 | PRETTY_NAME="Gentoo/Linux" 25 | ANSI_COLOR="1;32" 26 | HOME_URL="http://www.gentoo.org/" 27 | SUPPORT_URL="http://www.gentoo.org/main/en/support.xml" 28 | BUG_REPORT_URL="https://bugs.gentoo.org/" 29 | `) 30 | noPrettyName = []byte(`NAME="Ubuntu" 31 | VERSION="14.04, Trusty Tahr" 32 | ID=ubuntu 33 | ID_LIKE=debian 34 | VERSION_ID="14.04" 35 | HOME_URL="http://www.ubuntu.com/" 36 | SUPPORT_URL="http://help.ubuntu.com/" 37 | BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`) 38 | ) 39 | 40 | dir := os.TempDir() 41 | defer func() { 42 | etcOsRelease = backup 43 | os.RemoveAll(dir) 44 | }() 45 | 46 | etcOsRelease = filepath.Join(dir, "etcOsRelease") 47 | for expect, osRelease := range map[string][]byte{ 48 | "Ubuntu 14.04 LTS": ubuntuTrusty, 49 | "Gentoo/Linux": gentoo, 50 | "": noPrettyName, 51 | } { 52 | if err := ioutil.WriteFile(etcOsRelease, osRelease, 0600); err != nil { 53 | t.Fatalf("failed to write to %s: %v", etcOsRelease, err) 54 | } 55 | s, err := GetOperatingSystem() 56 | if s != expect { 57 | if expect == "" { 58 | t.Fatalf("Expected error 'PRETTY_NAME not found', but got %v", err) 59 | } else { 60 | t.Fatalf("Expected '%s', but got '%s'. Err=%v", expect, s, err) 61 | } 62 | } 63 | } 64 | } 65 | 66 | func TestIsContainerized(t *testing.T) { 67 | var ( 68 | backup = proc1Cgroup 69 | nonContainerizedProc1Cgroup = []byte(`14:name=systemd:/ 70 | 13:hugetlb:/ 71 | 12:net_prio:/ 72 | 11:perf_event:/ 73 | 10:bfqio:/ 74 | 9:blkio:/ 75 | 8:net_cls:/ 76 | 7:freezer:/ 77 | 6:devices:/ 78 | 5:memory:/ 79 | 4:cpuacct:/ 80 | 3:cpu:/ 81 | 2:cpuset:/ 82 | `) 83 | containerizedProc1Cgroup = []byte(`9:perf_event:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 84 | 8:blkio:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 85 | 7:net_cls:/ 86 | 6:freezer:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 87 | 5:devices:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 88 | 4:memory:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 89 | 3:cpuacct:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 90 | 2:cpu:/docker/3cef1b53c50b0fa357d994f8a1a8cd783c76bbf4f5dd08b226e38a8bd331338d 91 | 1:cpuset:/`) 92 | ) 93 | 94 | dir := os.TempDir() 95 | defer func() { 96 | proc1Cgroup = backup 97 | os.RemoveAll(dir) 98 | }() 99 | 100 | proc1Cgroup = filepath.Join(dir, "proc1Cgroup") 101 | 102 | if err := ioutil.WriteFile(proc1Cgroup, nonContainerizedProc1Cgroup, 0600); err != nil { 103 | t.Fatalf("failed to write to %s: %v", proc1Cgroup, err) 104 | } 105 | inContainer, err := IsContainerized() 106 | if err != nil { 107 | t.Fatal(err) 108 | } 109 | if inContainer { 110 | t.Fatal("Wrongly assuming containerized") 111 | } 112 | 113 | if err := ioutil.WriteFile(proc1Cgroup, containerizedProc1Cgroup, 0600); err != nil { 114 | t.Fatalf("failed to write to %s: %v", proc1Cgroup, err) 115 | } 116 | inContainer, err = IsContainerized() 117 | if err != nil { 118 | t.Fatal(err) 119 | } 120 | if !inContainer { 121 | t.Fatal("Wrongly assuming non-containerized") 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "io" 7 | "net" 8 | "net/http" 9 | "net/http/httputil" 10 | "os" 11 | "runtime" 12 | "strings" 13 | 14 | "github.com/docker/docker/api" 15 | "github.com/docker/docker/dockerversion" 16 | "github.com/docker/docker/pkg/log" 17 | "github.com/docker/docker/pkg/term" 18 | "github.com/docker/docker/utils" 19 | ) 20 | 21 | func (cli *DockerCli) dial() (net.Conn, error) { 22 | if cli.tlsConfig != nil && cli.proto != "unix" { 23 | return tls.Dial(cli.proto, cli.addr, cli.tlsConfig) 24 | } 25 | return net.Dial(cli.proto, cli.addr) 26 | } 27 | 28 | func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer) error { 29 | defer func() { 30 | if started != nil { 31 | close(started) 32 | } 33 | }() 34 | 35 | req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), nil) 36 | if err != nil { 37 | return err 38 | } 39 | req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) 40 | req.Header.Set("Content-Type", "plain/text") 41 | req.Host = cli.addr 42 | 43 | dial, err := cli.dial() 44 | if err != nil { 45 | if strings.Contains(err.Error(), "connection refused") { 46 | return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?") 47 | } 48 | return err 49 | } 50 | clientconn := httputil.NewClientConn(dial, nil) 51 | defer clientconn.Close() 52 | 53 | // Server hijacks the connection, error 'connection closed' expected 54 | clientconn.Do(req) 55 | 56 | rwc, br := clientconn.Hijack() 57 | defer rwc.Close() 58 | 59 | if started != nil { 60 | started <- rwc 61 | } 62 | 63 | var receiveStdout chan error 64 | 65 | var oldState *term.State 66 | 67 | if in != nil && setRawTerminal && cli.isTerminal && os.Getenv("NORAW") == "" { 68 | oldState, err = term.SetRawTerminal(cli.terminalFd) 69 | if err != nil { 70 | return err 71 | } 72 | defer term.RestoreTerminal(cli.terminalFd, oldState) 73 | } 74 | 75 | if stdout != nil || stderr != nil { 76 | receiveStdout = utils.Go(func() (err error) { 77 | defer func() { 78 | if in != nil { 79 | if setRawTerminal && cli.isTerminal { 80 | term.RestoreTerminal(cli.terminalFd, oldState) 81 | } 82 | // For some reason this Close call blocks on darwin.. 83 | // As the client exists right after, simply discard the close 84 | // until we find a better solution. 85 | if runtime.GOOS != "darwin" { 86 | in.Close() 87 | } 88 | } 89 | }() 90 | 91 | // When TTY is ON, use regular copy 92 | if setRawTerminal && stdout != nil { 93 | _, err = io.Copy(stdout, br) 94 | } else { 95 | _, err = utils.StdCopy(stdout, stderr, br) 96 | } 97 | log.Debugf("[hijack] End of stdout") 98 | return err 99 | }) 100 | } 101 | 102 | sendStdin := utils.Go(func() error { 103 | if in != nil { 104 | io.Copy(rwc, in) 105 | log.Debugf("[hijack] End of stdin") 106 | } 107 | if tcpc, ok := rwc.(*net.TCPConn); ok { 108 | if err := tcpc.CloseWrite(); err != nil { 109 | log.Debugf("Couldn't send EOF: %s", err) 110 | } 111 | } else if unixc, ok := rwc.(*net.UnixConn); ok { 112 | if err := unixc.CloseWrite(); err != nil { 113 | log.Debugf("Couldn't send EOF: %s", err) 114 | } 115 | } 116 | // Discard errors due to pipe interruption 117 | return nil 118 | }) 119 | 120 | if stdout != nil || stderr != nil { 121 | if err := <-receiveStdout; err != nil { 122 | log.Debugf("Error receiveStdout: %s", err) 123 | return err 124 | } 125 | } 126 | 127 | if !cli.isTerminal { 128 | if err := <-sendStdin; err != nil { 129 | log.Debugf("Error sendStdin: %s", err) 130 | return err 131 | } 132 | } 133 | return nil 134 | } 135 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/parsers_test.go: -------------------------------------------------------------------------------- 1 | package parsers 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestParseHost(t *testing.T) { 8 | var ( 9 | defaultHttpHost = "127.0.0.1" 10 | defaultUnix = "/var/run/docker.sock" 11 | ) 12 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.0"); err == nil { 13 | t.Errorf("tcp 0.0.0.0 address expected error return, but err == nil, got %s", addr) 14 | } 15 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://"); err == nil { 16 | t.Errorf("default tcp:// address expected error return, but err == nil, got %s", addr) 17 | } 18 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "0.0.0.1:5555"); err != nil || addr != "tcp://0.0.0.1:5555" { 19 | t.Errorf("0.0.0.1:5555 -> expected tcp://0.0.0.1:5555, got %s", addr) 20 | } 21 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, ":6666"); err != nil || addr != "tcp://127.0.0.1:6666" { 22 | t.Errorf(":6666 -> expected tcp://127.0.0.1:6666, got %s", addr) 23 | } 24 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "tcp://:7777"); err != nil || addr != "tcp://127.0.0.1:7777" { 25 | t.Errorf("tcp://:7777 -> expected tcp://127.0.0.1:7777, got %s", addr) 26 | } 27 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, ""); err != nil || addr != "unix:///var/run/docker.sock" { 28 | t.Errorf("empty argument -> expected unix:///var/run/docker.sock, got %s", addr) 29 | } 30 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix:///var/run/docker.sock"); err != nil || addr != "unix:///var/run/docker.sock" { 31 | t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr) 32 | } 33 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "unix://"); err != nil || addr != "unix:///var/run/docker.sock" { 34 | t.Errorf("unix:///var/run/docker.sock -> expected unix:///var/run/docker.sock, got %s", addr) 35 | } 36 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1"); err == nil { 37 | t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr) 38 | } 39 | if addr, err := ParseHost(defaultHttpHost, defaultUnix, "udp://127.0.0.1:2375"); err == nil { 40 | t.Errorf("udp protocol address expected error return, but err == nil. Got %s", addr) 41 | } 42 | } 43 | 44 | func TestParseRepositoryTag(t *testing.T) { 45 | if repo, tag := ParseRepositoryTag("root"); repo != "root" || tag != "" { 46 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "", repo, tag) 47 | } 48 | if repo, tag := ParseRepositoryTag("root:tag"); repo != "root" || tag != "tag" { 49 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "root", "tag", repo, tag) 50 | } 51 | if repo, tag := ParseRepositoryTag("user/repo"); repo != "user/repo" || tag != "" { 52 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "", repo, tag) 53 | } 54 | if repo, tag := ParseRepositoryTag("user/repo:tag"); repo != "user/repo" || tag != "tag" { 55 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "user/repo", "tag", repo, tag) 56 | } 57 | if repo, tag := ParseRepositoryTag("url:5000/repo"); repo != "url:5000/repo" || tag != "" { 58 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "", repo, tag) 59 | } 60 | if repo, tag := ParseRepositoryTag("url:5000/repo:tag"); repo != "url:5000/repo" || tag != "tag" { 61 | t.Errorf("Expected repo: '%s' and tag: '%s', got '%s' and '%s'", "url:5000/repo", "tag", repo, tag) 62 | } 63 | } 64 | 65 | func TestParsePortMapping(t *testing.T) { 66 | data, err := PartParser("ip:public:private", "192.168.1.1:80:8080") 67 | if err != nil { 68 | t.Fatal(err) 69 | } 70 | 71 | if len(data) != 3 { 72 | t.FailNow() 73 | } 74 | if data["ip"] != "192.168.1.1" { 75 | t.Fail() 76 | } 77 | if data["public"] != "80" { 78 | t.Fail() 79 | } 80 | if data["private"] != "8080" { 81 | t.Fail() 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/engine_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestRegister(t *testing.T) { 10 | if err := Register("dummy1", nil); err != nil { 11 | t.Fatal(err) 12 | } 13 | 14 | if err := Register("dummy1", nil); err == nil { 15 | t.Fatalf("Expecting error, got none") 16 | } 17 | // Register is global so let's cleanup to avoid conflicts 18 | defer unregister("dummy1") 19 | 20 | eng := New() 21 | 22 | //Should fail because global handlers are copied 23 | //at the engine creation 24 | if err := eng.Register("dummy1", nil); err == nil { 25 | t.Fatalf("Expecting error, got none") 26 | } 27 | 28 | if err := eng.Register("dummy2", nil); err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | if err := eng.Register("dummy2", nil); err == nil { 33 | t.Fatalf("Expecting error, got none") 34 | } 35 | defer unregister("dummy2") 36 | } 37 | 38 | func TestJob(t *testing.T) { 39 | eng := New() 40 | job1 := eng.Job("dummy1", "--level=awesome") 41 | 42 | if job1.handler != nil { 43 | t.Fatalf("job1.handler should be empty") 44 | } 45 | 46 | h := func(j *Job) Status { 47 | j.Printf("%s\n", j.Name) 48 | return 42 49 | } 50 | 51 | eng.Register("dummy2", h) 52 | defer unregister("dummy2") 53 | job2 := eng.Job("dummy2", "--level=awesome") 54 | 55 | if job2.handler == nil { 56 | t.Fatalf("job2.handler shouldn't be nil") 57 | } 58 | 59 | if job2.handler(job2) != 42 { 60 | t.Fatalf("handler dummy2 was not found in job2") 61 | } 62 | } 63 | 64 | func TestEngineCommands(t *testing.T) { 65 | eng := New() 66 | handler := func(job *Job) Status { return StatusOK } 67 | eng.Register("foo", handler) 68 | eng.Register("bar", handler) 69 | eng.Register("echo", handler) 70 | eng.Register("die", handler) 71 | var output bytes.Buffer 72 | commands := eng.Job("commands") 73 | commands.Stdout.Add(&output) 74 | commands.Run() 75 | expected := "bar\ncommands\ndie\necho\nfoo\n" 76 | if result := output.String(); result != expected { 77 | t.Fatalf("Unexpected output:\nExpected = %v\nResult = %v\n", expected, result) 78 | } 79 | } 80 | 81 | func TestEngineString(t *testing.T) { 82 | eng1 := New() 83 | eng2 := New() 84 | s1 := eng1.String() 85 | s2 := eng2.String() 86 | if eng1 == eng2 { 87 | t.Fatalf("Different engines should have different names (%v == %v)", s1, s2) 88 | } 89 | } 90 | 91 | func TestEngineLogf(t *testing.T) { 92 | eng := New() 93 | input := "Test log line" 94 | if n, err := eng.Logf("%s\n", input); err != nil { 95 | t.Fatal(err) 96 | } else if n < len(input) { 97 | t.Fatalf("Test: Logf() should print at least as much as the input\ninput=%d\nprinted=%d", len(input), n) 98 | } 99 | } 100 | 101 | func TestParseJob(t *testing.T) { 102 | eng := New() 103 | // Verify that the resulting job calls to the right place 104 | var called bool 105 | eng.Register("echo", func(job *Job) Status { 106 | called = true 107 | return StatusOK 108 | }) 109 | input := "echo DEBUG=1 hello world VERBOSITY=42" 110 | job, err := eng.ParseJob(input) 111 | if err != nil { 112 | t.Fatal(err) 113 | } 114 | if job.Name != "echo" { 115 | t.Fatalf("Invalid job name: %v", job.Name) 116 | } 117 | if strings.Join(job.Args, ":::") != "hello:::world" { 118 | t.Fatalf("Invalid job args: %v", job.Args) 119 | } 120 | if job.Env().Get("DEBUG") != "1" { 121 | t.Fatalf("Invalid job env: %v", job.Env) 122 | } 123 | if job.Env().Get("VERBOSITY") != "42" { 124 | t.Fatalf("Invalid job env: %v", job.Env) 125 | } 126 | if len(job.Env().Map()) != 2 { 127 | t.Fatalf("Invalid job env: %v", job.Env) 128 | } 129 | if err := job.Run(); err != nil { 130 | t.Fatal(err) 131 | } 132 | if !called { 133 | t.Fatalf("Job was not called") 134 | } 135 | } 136 | 137 | func TestCatchallEmptyName(t *testing.T) { 138 | eng := New() 139 | var called bool 140 | eng.RegisterCatchall(func(job *Job) Status { 141 | called = true 142 | return StatusOK 143 | }) 144 | err := eng.Job("").Run() 145 | if err == nil { 146 | t.Fatalf("Engine.Job(\"\").Run() should return an error") 147 | } 148 | if called { 149 | t.Fatalf("Engine.Job(\"\").Run() should return an error") 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker_test 6 | 7 | import ( 8 | "archive/tar" 9 | "bytes" 10 | "fmt" 11 | "github.com/fsouza/go-dockerclient" 12 | "io" 13 | "log" 14 | "time" 15 | ) 16 | 17 | func ExampleClient_AttachToContainer() { 18 | client, err := docker.NewClient("http://localhost:4243") 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | client.SkipServerVersionCheck = true 23 | // Reading logs from container a84849 and sending them to buf. 24 | var buf bytes.Buffer 25 | err = client.AttachToContainer(docker.AttachToContainerOptions{ 26 | Container: "a84849", 27 | OutputStream: &buf, 28 | Logs: true, 29 | Stdout: true, 30 | Stderr: true, 31 | }) 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | log.Println(buf.String()) 36 | buf.Reset() 37 | err = client.AttachToContainer(docker.AttachToContainerOptions{ 38 | Container: "a84849", 39 | OutputStream: &buf, 40 | Stdout: true, 41 | Stream: true, 42 | }) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | log.Println(buf.String()) 47 | } 48 | 49 | func ExampleClient_CopyFromContainer() { 50 | client, err := docker.NewClient("http://localhost:4243") 51 | if err != nil { 52 | log.Fatal(err) 53 | } 54 | cid := "a84849" 55 | var buf bytes.Buffer 56 | filename := "/tmp/output.txt" 57 | err = client.CopyFromContainer(docker.CopyFromContainerOptions{ 58 | Container: cid, 59 | Resource: filename, 60 | OutputStream: &buf, 61 | }) 62 | if err != nil { 63 | log.Fatalf("Error while copying from %s: %s\n", cid, err) 64 | } 65 | content := new(bytes.Buffer) 66 | r := bytes.NewReader(buf.Bytes()) 67 | tr := tar.NewReader(r) 68 | tr.Next() 69 | if err != nil && err != io.EOF { 70 | log.Fatal(err) 71 | } 72 | if _, err := io.Copy(content, tr); err != nil { 73 | log.Fatal(err) 74 | } 75 | log.Println(buf.String()) 76 | } 77 | 78 | func ExampleClient_BuildImage() { 79 | client, err := docker.NewClient("http://localhost:4243") 80 | if err != nil { 81 | log.Fatal(err) 82 | } 83 | 84 | t := time.Now() 85 | inputbuf, outputbuf := bytes.NewBuffer(nil), bytes.NewBuffer(nil) 86 | tr := tar.NewWriter(inputbuf) 87 | tr.WriteHeader(&tar.Header{Name: "Dockerfile", Size: 10, ModTime: t, AccessTime: t, ChangeTime: t}) 88 | tr.Write([]byte("FROM base\n")) 89 | tr.Close() 90 | opts := docker.BuildImageOptions{ 91 | Name: "test", 92 | InputStream: inputbuf, 93 | OutputStream: outputbuf, 94 | } 95 | if err := client.BuildImage(opts); err != nil { 96 | log.Fatal(err) 97 | } 98 | } 99 | 100 | func ExampleClient_ListenEvents() { 101 | client, err := docker.NewClient("http://localhost:4243") 102 | if err != nil { 103 | log.Fatal(err) 104 | } 105 | 106 | listener := make(chan *docker.APIEvents) 107 | err = client.AddEventListener(listener) 108 | if err != nil { 109 | log.Fatal(err) 110 | } 111 | 112 | defer func() { 113 | 114 | err = client.RemoveEventListener(listener) 115 | if err != nil { 116 | log.Fatal(err) 117 | } 118 | 119 | }() 120 | 121 | timeout := time.After(1 * time.Second) 122 | 123 | for { 124 | select { 125 | case msg := <-listener: 126 | log.Println(msg) 127 | case <-timeout: 128 | break 129 | } 130 | } 131 | 132 | } 133 | 134 | func ExampleEnv_Map() { 135 | e := docker.Env([]string{"A=1", "B=2", "C=3"}) 136 | envs := e.Map() 137 | for k, v := range envs { 138 | fmt.Printf("%s=%q\n", k, v) 139 | } 140 | } 141 | 142 | func ExampleEnv_SetJSON() { 143 | type Person struct { 144 | Name string 145 | Age int 146 | } 147 | p := Person{Name: "Gopher", Age: 4} 148 | var e docker.Env 149 | err := e.SetJSON("person", p) 150 | if err != nil { 151 | log.Fatal(err) 152 | } 153 | } 154 | 155 | func ExampleEnv_GetJSON() { 156 | type Person struct { 157 | Name string 158 | Age int 159 | } 160 | p := Person{Name: "Gopher", Age: 4} 161 | var e docker.Env 162 | e.Set("person", `{"name":"Gopher","age":4}`) 163 | err := e.GetJSON("person", &p) 164 | if err != nil { 165 | log.Fatal(err) 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | "testing" 9 | ) 10 | 11 | func TestBufReader(t *testing.T) { 12 | reader, writer := io.Pipe() 13 | bufreader := NewBufReader(reader) 14 | 15 | // Write everything down to a Pipe 16 | // Usually, a pipe should block but because of the buffered reader, 17 | // the writes will go through 18 | done := make(chan bool) 19 | go func() { 20 | writer.Write([]byte("hello world")) 21 | writer.Close() 22 | done <- true 23 | }() 24 | 25 | // Drain the reader *after* everything has been written, just to verify 26 | // it is indeed buffering 27 | <-done 28 | output, err := ioutil.ReadAll(bufreader) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | if !bytes.Equal(output, []byte("hello world")) { 33 | t.Error(string(output)) 34 | } 35 | } 36 | 37 | func TestCheckLocalDns(t *testing.T) { 38 | for resolv, result := range map[string]bool{`# Dynamic 39 | nameserver 10.0.2.3 40 | search docker.com`: false, 41 | `# Dynamic 42 | #nameserver 127.0.0.1 43 | nameserver 10.0.2.3 44 | search docker.com`: false, 45 | `# Dynamic 46 | nameserver 10.0.2.3 #not used 127.0.1.1 47 | search docker.com`: false, 48 | `# Dynamic 49 | #nameserver 10.0.2.3 50 | #search docker.com`: true, 51 | `# Dynamic 52 | nameserver 127.0.0.1 53 | search docker.com`: true, 54 | `# Dynamic 55 | nameserver 127.0.1.1 56 | search docker.com`: true, 57 | `# Dynamic 58 | `: true, 59 | ``: true, 60 | } { 61 | if CheckLocalDns([]byte(resolv)) != result { 62 | t.Fatalf("Wrong local dns detection: {%s} should be %v", resolv, result) 63 | } 64 | } 65 | } 66 | func TestReplaceAndAppendEnvVars(t *testing.T) { 67 | var ( 68 | d = []string{"HOME=/"} 69 | o = []string{"HOME=/root", "TERM=xterm"} 70 | ) 71 | 72 | env := ReplaceOrAppendEnvValues(d, o) 73 | if len(env) != 2 { 74 | t.Fatalf("expected len of 2 got %d", len(env)) 75 | } 76 | if env[0] != "HOME=/root" { 77 | t.Fatalf("expected HOME=/root got '%s'", env[0]) 78 | } 79 | if env[1] != "TERM=xterm" { 80 | t.Fatalf("expected TERM=xterm got '%s'", env[1]) 81 | } 82 | } 83 | 84 | // Reading a symlink to a directory must return the directory 85 | func TestReadSymlinkedDirectoryExistingDirectory(t *testing.T) { 86 | var err error 87 | if err = os.Mkdir("/tmp/testReadSymlinkToExistingDirectory", 0777); err != nil { 88 | t.Errorf("failed to create directory: %s", err) 89 | } 90 | 91 | if err = os.Symlink("/tmp/testReadSymlinkToExistingDirectory", "/tmp/dirLinkTest"); err != nil { 92 | t.Errorf("failed to create symlink: %s", err) 93 | } 94 | 95 | var path string 96 | if path, err = ReadSymlinkedDirectory("/tmp/dirLinkTest"); err != nil { 97 | t.Fatalf("failed to read symlink to directory: %s", err) 98 | } 99 | 100 | if path != "/tmp/testReadSymlinkToExistingDirectory" { 101 | t.Fatalf("symlink returned unexpected directory: %s", path) 102 | } 103 | 104 | if err = os.Remove("/tmp/testReadSymlinkToExistingDirectory"); err != nil { 105 | t.Errorf("failed to remove temporary directory: %s", err) 106 | } 107 | 108 | if err = os.Remove("/tmp/dirLinkTest"); err != nil { 109 | t.Errorf("failed to remove symlink: %s", err) 110 | } 111 | } 112 | 113 | // Reading a non-existing symlink must fail 114 | func TestReadSymlinkedDirectoryNonExistingSymlink(t *testing.T) { 115 | var path string 116 | var err error 117 | if path, err = ReadSymlinkedDirectory("/tmp/test/foo/Non/ExistingPath"); err == nil { 118 | t.Fatalf("error expected for non-existing symlink") 119 | } 120 | 121 | if path != "" { 122 | t.Fatalf("expected empty path, but '%s' was returned", path) 123 | } 124 | } 125 | 126 | // Reading a symlink to a file must fail 127 | func TestReadSymlinkedDirectoryToFile(t *testing.T) { 128 | var err error 129 | var file *os.File 130 | 131 | if file, err = os.Create("/tmp/testReadSymlinkToFile"); err != nil { 132 | t.Fatalf("failed to create file: %s", err) 133 | } 134 | 135 | file.Close() 136 | 137 | if err = os.Symlink("/tmp/testReadSymlinkToFile", "/tmp/fileLinkTest"); err != nil { 138 | t.Errorf("failed to create symlink: %s", err) 139 | } 140 | 141 | var path string 142 | if path, err = ReadSymlinkedDirectory("/tmp/fileLinkTest"); err == nil { 143 | t.Fatalf("ReadSymlinkedDirectory on a symlink to a file should've failed") 144 | } 145 | 146 | if path != "" { 147 | t.Fatalf("path should've been empty: %s", path) 148 | } 149 | 150 | if err = os.Remove("/tmp/testReadSymlinkToFile"); err != nil { 151 | t.Errorf("failed to remove file: %s", err) 152 | } 153 | 154 | if err = os.Remove("/tmp/fileLinkTest"); err != nil { 155 | t.Errorf("failed to remove symlink: %s", err) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/http.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "strings" 7 | 8 | "github.com/docker/docker/pkg/log" 9 | ) 10 | 11 | // VersionInfo is used to model entities which has a version. 12 | // It is basically a tupple with name and version. 13 | type VersionInfo interface { 14 | Name() string 15 | Version() string 16 | } 17 | 18 | func validVersion(version VersionInfo) bool { 19 | const stopChars = " \t\r\n/" 20 | name := version.Name() 21 | vers := version.Version() 22 | if len(name) == 0 || strings.ContainsAny(name, stopChars) { 23 | return false 24 | } 25 | if len(vers) == 0 || strings.ContainsAny(vers, stopChars) { 26 | return false 27 | } 28 | return true 29 | } 30 | 31 | // Convert versions to a string and append the string to the string base. 32 | // 33 | // Each VersionInfo will be converted to a string in the format of 34 | // "product/version", where the "product" is get from the Name() method, while 35 | // version is get from the Version() method. Several pieces of verson information 36 | // will be concatinated and separated by space. 37 | func appendVersions(base string, versions ...VersionInfo) string { 38 | if len(versions) == 0 { 39 | return base 40 | } 41 | 42 | verstrs := make([]string, 0, 1+len(versions)) 43 | if len(base) > 0 { 44 | verstrs = append(verstrs, base) 45 | } 46 | 47 | for _, v := range versions { 48 | if !validVersion(v) { 49 | continue 50 | } 51 | verstrs = append(verstrs, v.Name()+"/"+v.Version()) 52 | } 53 | return strings.Join(verstrs, " ") 54 | } 55 | 56 | // HTTPRequestDecorator is used to change an instance of 57 | // http.Request. It could be used to add more header fields, 58 | // change body, etc. 59 | type HTTPRequestDecorator interface { 60 | // ChangeRequest() changes the request accordingly. 61 | // The changed request will be returned or err will be non-nil 62 | // if an error occur. 63 | ChangeRequest(req *http.Request) (newReq *http.Request, err error) 64 | } 65 | 66 | // HTTPUserAgentDecorator appends the product/version to the user agent field 67 | // of a request. 68 | type HTTPUserAgentDecorator struct { 69 | versions []VersionInfo 70 | } 71 | 72 | func NewHTTPUserAgentDecorator(versions ...VersionInfo) HTTPRequestDecorator { 73 | return &HTTPUserAgentDecorator{ 74 | versions: versions, 75 | } 76 | } 77 | 78 | func (h *HTTPUserAgentDecorator) ChangeRequest(req *http.Request) (newReq *http.Request, err error) { 79 | if req == nil { 80 | return req, nil 81 | } 82 | 83 | userAgent := appendVersions(req.UserAgent(), h.versions...) 84 | if len(userAgent) > 0 { 85 | req.Header.Set("User-Agent", userAgent) 86 | } 87 | return req, nil 88 | } 89 | 90 | type HTTPMetaHeadersDecorator struct { 91 | Headers map[string][]string 92 | } 93 | 94 | func (h *HTTPMetaHeadersDecorator) ChangeRequest(req *http.Request) (newReq *http.Request, err error) { 95 | if h.Headers == nil { 96 | return req, nil 97 | } 98 | for k, v := range h.Headers { 99 | req.Header[k] = v 100 | } 101 | return req, nil 102 | } 103 | 104 | type HTTPAuthDecorator struct { 105 | login string 106 | password string 107 | } 108 | 109 | func NewHTTPAuthDecorator(login, password string) HTTPRequestDecorator { 110 | return &HTTPAuthDecorator{ 111 | login: login, 112 | password: password, 113 | } 114 | } 115 | 116 | func (self *HTTPAuthDecorator) ChangeRequest(req *http.Request) (*http.Request, error) { 117 | req.SetBasicAuth(self.login, self.password) 118 | return req, nil 119 | } 120 | 121 | // HTTPRequestFactory creates an HTTP request 122 | // and applies a list of decorators on the request. 123 | type HTTPRequestFactory struct { 124 | decorators []HTTPRequestDecorator 125 | } 126 | 127 | func NewHTTPRequestFactory(d ...HTTPRequestDecorator) *HTTPRequestFactory { 128 | return &HTTPRequestFactory{ 129 | decorators: d, 130 | } 131 | } 132 | 133 | func (self *HTTPRequestFactory) AddDecorator(d ...HTTPRequestDecorator) { 134 | self.decorators = append(self.decorators, d...) 135 | } 136 | 137 | // NewRequest() creates a new *http.Request, 138 | // applies all decorators in the HTTPRequestFactory on the request, 139 | // then applies decorators provided by d on the request. 140 | func (h *HTTPRequestFactory) NewRequest(method, urlStr string, body io.Reader, d ...HTTPRequestDecorator) (*http.Request, error) { 141 | req, err := http.NewRequest(method, urlStr, body) 142 | if err != nil { 143 | return nil, err 144 | } 145 | 146 | // By default, a nil factory should work. 147 | if h == nil { 148 | return req, nil 149 | } 150 | for _, dec := range h.decorators { 151 | req, err = dec.ChangeRequest(req) 152 | if err != nil { 153 | return nil, err 154 | } 155 | } 156 | for _, dec := range d { 157 | req, err = dec.ChangeRequest(req) 158 | if err != nil { 159 | return nil, err 160 | } 161 | } 162 | log.Debugf("%v -- HEADERS: %v", req.URL, req.Header) 163 | return req, err 164 | } 165 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/jsonmessage.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "strings" 8 | "time" 9 | 10 | "github.com/docker/docker/pkg/term" 11 | "github.com/docker/docker/pkg/units" 12 | ) 13 | 14 | type JSONError struct { 15 | Code int `json:"code,omitempty"` 16 | Message string `json:"message,omitempty"` 17 | } 18 | 19 | func (e *JSONError) Error() string { 20 | return e.Message 21 | } 22 | 23 | type JSONProgress struct { 24 | terminalFd uintptr 25 | Current int `json:"current,omitempty"` 26 | Total int `json:"total,omitempty"` 27 | Start int64 `json:"start,omitempty"` 28 | } 29 | 30 | func (p *JSONProgress) String() string { 31 | var ( 32 | width = 200 33 | pbBox string 34 | numbersBox string 35 | timeLeftBox string 36 | ) 37 | 38 | ws, err := term.GetWinsize(p.terminalFd) 39 | if err == nil { 40 | width = int(ws.Width) 41 | } 42 | 43 | if p.Current <= 0 && p.Total <= 0 { 44 | return "" 45 | } 46 | current := units.HumanSize(int64(p.Current)) 47 | if p.Total <= 0 { 48 | return fmt.Sprintf("%8v", current) 49 | } 50 | total := units.HumanSize(int64(p.Total)) 51 | percentage := int(float64(p.Current)/float64(p.Total)*100) / 2 52 | if width > 110 { 53 | // this number can't be negetive gh#7136 54 | numSpaces := 0 55 | if 50-percentage > 0 { 56 | numSpaces = 50 - percentage 57 | } 58 | pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces)) 59 | } 60 | numbersBox = fmt.Sprintf("%8v/%v", current, total) 61 | 62 | if p.Current > 0 && p.Start > 0 && percentage < 50 { 63 | fromStart := time.Now().UTC().Sub(time.Unix(int64(p.Start), 0)) 64 | perEntry := fromStart / time.Duration(p.Current) 65 | left := time.Duration(p.Total-p.Current) * perEntry 66 | left = (left / time.Second) * time.Second 67 | 68 | if width > 50 { 69 | timeLeftBox = " " + left.String() 70 | } 71 | } 72 | return pbBox + numbersBox + timeLeftBox 73 | } 74 | 75 | type JSONMessage struct { 76 | Stream string `json:"stream,omitempty"` 77 | Status string `json:"status,omitempty"` 78 | Progress *JSONProgress `json:"progressDetail,omitempty"` 79 | ProgressMessage string `json:"progress,omitempty"` //deprecated 80 | ID string `json:"id,omitempty"` 81 | From string `json:"from,omitempty"` 82 | Time int64 `json:"time,omitempty"` 83 | Error *JSONError `json:"errorDetail,omitempty"` 84 | ErrorMessage string `json:"error,omitempty"` //deprecated 85 | } 86 | 87 | func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { 88 | if jm.Error != nil { 89 | if jm.Error.Code == 401 { 90 | return fmt.Errorf("Authentication is required.") 91 | } 92 | return jm.Error 93 | } 94 | var endl string 95 | if isTerminal && jm.Stream == "" && jm.Progress != nil { 96 | // [2K = erase entire current line 97 | fmt.Fprintf(out, "%c[2K\r", 27) 98 | endl = "\r" 99 | } else if jm.Progress != nil { //disable progressbar in non-terminal 100 | return nil 101 | } 102 | if jm.Time != 0 { 103 | fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(time.RFC3339Nano)) 104 | } 105 | if jm.ID != "" { 106 | fmt.Fprintf(out, "%s: ", jm.ID) 107 | } 108 | if jm.From != "" { 109 | fmt.Fprintf(out, "(from %s) ", jm.From) 110 | } 111 | if jm.Progress != nil { 112 | fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl) 113 | } else if jm.ProgressMessage != "" { //deprecated 114 | fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl) 115 | } else if jm.Stream != "" { 116 | fmt.Fprintf(out, "%s%s", jm.Stream, endl) 117 | } else { 118 | fmt.Fprintf(out, "%s%s\n", jm.Status, endl) 119 | } 120 | return nil 121 | } 122 | 123 | func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool) error { 124 | var ( 125 | dec = json.NewDecoder(in) 126 | ids = make(map[string]int) 127 | diff = 0 128 | ) 129 | for { 130 | var jm JSONMessage 131 | if err := dec.Decode(&jm); err != nil { 132 | if err == io.EOF { 133 | break 134 | } 135 | return err 136 | } 137 | 138 | if jm.Progress != nil { 139 | jm.Progress.terminalFd = terminalFd 140 | } 141 | if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") { 142 | line, ok := ids[jm.ID] 143 | if !ok { 144 | line = len(ids) 145 | ids[jm.ID] = line 146 | fmt.Fprintf(out, "\n") 147 | diff = 0 148 | } else { 149 | diff = len(ids) - line 150 | } 151 | if jm.ID != "" && isTerminal { 152 | // [{diff}A = move cursor up diff rows 153 | fmt.Fprintf(out, "%c[%dA", 27, diff) 154 | } 155 | } 156 | err := jm.Display(out, isTerminal) 157 | if jm.ID != "" && isTerminal { 158 | // [{diff}B = move cursor down diff rows 159 | fmt.Fprintf(out, "%c[%dB", 27, diff) 160 | } 161 | if err != nil { 162 | return err 163 | } 164 | } 165 | return nil 166 | } 167 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/misc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "net/http" 9 | "net/url" 10 | "reflect" 11 | "sort" 12 | "testing" 13 | ) 14 | 15 | type DockerVersion struct { 16 | Version string 17 | GitCommit string 18 | GoVersion string 19 | } 20 | 21 | func TestVersion(t *testing.T) { 22 | body := `{ 23 | "Version":"0.2.2", 24 | "GitCommit":"5a2a5cc+CHANGES", 25 | "GoVersion":"go1.0.3" 26 | }` 27 | fakeRT := FakeRoundTripper{message: body, status: http.StatusOK} 28 | client := newTestClient(&fakeRT) 29 | expected := DockerVersion{ 30 | Version: "0.2.2", 31 | GitCommit: "5a2a5cc+CHANGES", 32 | GoVersion: "go1.0.3", 33 | } 34 | version, err := client.Version() 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | if result := version.Get("Version"); result != expected.Version { 40 | t.Errorf("Version(): Wrong result. Want %#v. Got %#v.", expected.Version, version.Get("Version")) 41 | } 42 | if result := version.Get("GitCommit"); result != expected.GitCommit { 43 | t.Errorf("GitCommit(): Wrong result. Want %#v. Got %#v.", expected.GitCommit, version.Get("GitCommit")) 44 | } 45 | if result := version.Get("GoVersion"); result != expected.GoVersion { 46 | t.Errorf("GoVersion(): Wrong result. Want %#v. Got %#v.", expected.GoVersion, version.Get("GoVersion")) 47 | } 48 | req := fakeRT.requests[0] 49 | if req.Method != "GET" { 50 | t.Errorf("Version(): wrong request method. Want GET. Got %s.", req.Method) 51 | } 52 | u, _ := url.Parse(client.getURL("/version")) 53 | if req.URL.Path != u.Path { 54 | t.Errorf("Version(): wrong request path. Want %q. Got %q.", u.Path, req.URL.Path) 55 | } 56 | } 57 | 58 | func TestVersionError(t *testing.T) { 59 | fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError} 60 | client := newTestClient(fakeRT) 61 | version, err := client.Version() 62 | if version != nil { 63 | t.Errorf("Version(): expected value, got %#v.", version) 64 | } 65 | if err == nil { 66 | t.Error("Version(): unexpected error") 67 | } 68 | } 69 | 70 | func TestInfo(t *testing.T) { 71 | body := `{ 72 | "Containers":11, 73 | "Images":16, 74 | "Debug":0, 75 | "NFd":11, 76 | "NGoroutines":21, 77 | "MemoryLimit":1, 78 | "SwapLimit":0 79 | }` 80 | fakeRT := FakeRoundTripper{message: body, status: http.StatusOK} 81 | client := newTestClient(&fakeRT) 82 | expected := Env{} 83 | expected.SetInt("Containers", 11) 84 | expected.SetInt("Images", 16) 85 | expected.SetBool("Debug", false) 86 | expected.SetInt("NFd", 11) 87 | expected.SetInt("NGoroutines", 21) 88 | expected.SetBool("MemoryLimit", true) 89 | expected.SetBool("SwapLimit", false) 90 | info, err := client.Info() 91 | if err != nil { 92 | t.Fatal(err) 93 | } 94 | infoSlice := []string(*info) 95 | expectedSlice := []string(expected) 96 | sort.Strings(infoSlice) 97 | sort.Strings(expectedSlice) 98 | if !reflect.DeepEqual(expectedSlice, infoSlice) { 99 | t.Errorf("Info(): Wrong result.\nWant %#v.\nGot %#v.", expected, *info) 100 | } 101 | req := fakeRT.requests[0] 102 | if req.Method != "GET" { 103 | t.Errorf("Info(): Wrong HTTP method. Want GET. Got %s.", req.Method) 104 | } 105 | u, _ := url.Parse(client.getURL("/info")) 106 | if req.URL.Path != u.Path { 107 | t.Errorf("Info(): Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path) 108 | } 109 | } 110 | 111 | func TestInfoError(t *testing.T) { 112 | fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError} 113 | client := newTestClient(fakeRT) 114 | version, err := client.Info() 115 | if version != nil { 116 | t.Errorf("Info(): expected value, got %#v.", version) 117 | } 118 | if err == nil { 119 | t.Error("Info(): unexpected error") 120 | } 121 | } 122 | 123 | func TestParseRepositoryTag(t *testing.T) { 124 | var tests = []struct { 125 | input string 126 | expectedRepo string 127 | expectedTag string 128 | }{ 129 | { 130 | "localhost.localdomain:5000/samalba/hipache:latest", 131 | "localhost.localdomain:5000/samalba/hipache", 132 | "latest", 133 | }, 134 | { 135 | "localhost.localdomain:5000/samalba/hipache", 136 | "localhost.localdomain:5000/samalba/hipache", 137 | "", 138 | }, 139 | { 140 | "tsuru/python", 141 | "tsuru/python", 142 | "", 143 | }, 144 | { 145 | "tsuru/python:2.7", 146 | "tsuru/python", 147 | "2.7", 148 | }, 149 | } 150 | for _, tt := range tests { 151 | repo, tag := ParseRepositoryTag(tt.input) 152 | if repo != tt.expectedRepo { 153 | t.Errorf("ParseRepositoryTag(%q): wrong repository. Want %q. Got %q", tt.input, tt.expectedRepo, repo) 154 | } 155 | if tag != tt.expectedTag { 156 | t.Errorf("ParseRepositoryTag(%q): wrong tag. Want %q. Got %q", tt.input, tt.expectedTag, tag) 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/utils/stdcopy.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "io" 7 | 8 | "github.com/docker/docker/pkg/log" 9 | ) 10 | 11 | const ( 12 | StdWriterPrefixLen = 8 13 | StdWriterFdIndex = 0 14 | StdWriterSizeIndex = 4 15 | ) 16 | 17 | type StdType [StdWriterPrefixLen]byte 18 | 19 | var ( 20 | Stdin StdType = StdType{0: 0} 21 | Stdout StdType = StdType{0: 1} 22 | Stderr StdType = StdType{0: 2} 23 | ) 24 | 25 | type StdWriter struct { 26 | io.Writer 27 | prefix StdType 28 | sizeBuf []byte 29 | } 30 | 31 | func (w *StdWriter) Write(buf []byte) (n int, err error) { 32 | if w == nil || w.Writer == nil { 33 | return 0, errors.New("Writer not instanciated") 34 | } 35 | binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf))) 36 | buf = append(w.prefix[:], buf...) 37 | 38 | n, err = w.Writer.Write(buf) 39 | return n - StdWriterPrefixLen, err 40 | } 41 | 42 | // NewStdWriter instanciates a new Writer. 43 | // Everything written to it will be encapsulated using a custom format, 44 | // and written to the underlying `w` stream. 45 | // This allows multiple write streams (e.g. stdout and stderr) to be muxed into a single connection. 46 | // `t` indicates the id of the stream to encapsulate. 47 | // It can be utils.Stdin, utils.Stdout, utils.Stderr. 48 | func NewStdWriter(w io.Writer, t StdType) *StdWriter { 49 | if len(t) != StdWriterPrefixLen { 50 | return nil 51 | } 52 | 53 | return &StdWriter{ 54 | Writer: w, 55 | prefix: t, 56 | sizeBuf: make([]byte, 4), 57 | } 58 | } 59 | 60 | var ErrInvalidStdHeader = errors.New("Unrecognized input header") 61 | 62 | // StdCopy is a modified version of io.Copy. 63 | // 64 | // StdCopy will demultiplex `src`, assuming that it contains two streams, 65 | // previously multiplexed together using a StdWriter instance. 66 | // As it reads from `src`, StdCopy will write to `dstout` and `dsterr`. 67 | // 68 | // StdCopy will read until it hits EOF on `src`. It will then return a nil error. 69 | // In other words: if `err` is non nil, it indicates a real underlying error. 70 | // 71 | // `written` will hold the total number of bytes written to `dstout` and `dsterr`. 72 | func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) { 73 | var ( 74 | buf = make([]byte, 32*1024+StdWriterPrefixLen+1) 75 | bufLen = len(buf) 76 | nr, nw int 77 | er, ew error 78 | out io.Writer 79 | frameSize int 80 | ) 81 | 82 | for { 83 | // Make sure we have at least a full header 84 | for nr < StdWriterPrefixLen { 85 | var nr2 int 86 | nr2, er = src.Read(buf[nr:]) 87 | nr += nr2 88 | if er == io.EOF { 89 | if nr < StdWriterPrefixLen { 90 | log.Debugf("Corrupted prefix: %v", buf[:nr]) 91 | return written, nil 92 | } 93 | break 94 | } 95 | if er != nil { 96 | log.Debugf("Error reading header: %s", er) 97 | return 0, er 98 | } 99 | } 100 | 101 | // Check the first byte to know where to write 102 | switch buf[StdWriterFdIndex] { 103 | case 0: 104 | fallthrough 105 | case 1: 106 | // Write on stdout 107 | out = dstout 108 | case 2: 109 | // Write on stderr 110 | out = dsterr 111 | default: 112 | log.Debugf("Error selecting output fd: (%d)", buf[StdWriterFdIndex]) 113 | return 0, ErrInvalidStdHeader 114 | } 115 | 116 | // Retrieve the size of the frame 117 | frameSize = int(binary.BigEndian.Uint32(buf[StdWriterSizeIndex : StdWriterSizeIndex+4])) 118 | log.Debugf("framesize: %d", frameSize) 119 | 120 | // Check if the buffer is big enough to read the frame. 121 | // Extend it if necessary. 122 | if frameSize+StdWriterPrefixLen > bufLen { 123 | log.Debugf("Extending buffer cap by %d (was %d)", frameSize+StdWriterPrefixLen-bufLen+1, len(buf)) 124 | buf = append(buf, make([]byte, frameSize+StdWriterPrefixLen-bufLen+1)...) 125 | bufLen = len(buf) 126 | } 127 | 128 | // While the amount of bytes read is less than the size of the frame + header, we keep reading 129 | for nr < frameSize+StdWriterPrefixLen { 130 | var nr2 int 131 | nr2, er = src.Read(buf[nr:]) 132 | nr += nr2 133 | if er == io.EOF { 134 | if nr < frameSize+StdWriterPrefixLen { 135 | log.Debugf("Corrupted frame: %v", buf[StdWriterPrefixLen:nr]) 136 | return written, nil 137 | } 138 | break 139 | } 140 | if er != nil { 141 | log.Debugf("Error reading frame: %s", er) 142 | return 0, er 143 | } 144 | } 145 | 146 | // Write the retrieved frame (without header) 147 | nw, ew = out.Write(buf[StdWriterPrefixLen : frameSize+StdWriterPrefixLen]) 148 | if ew != nil { 149 | log.Debugf("Error writing frame: %s", ew) 150 | return 0, ew 151 | } 152 | // If the frame has not been fully written: error 153 | if nw != frameSize { 154 | log.Debugf("Error Short Write: (%d on %d)", nw, frameSize) 155 | return 0, io.ErrShortWrite 156 | } 157 | written += int64(nw) 158 | 159 | // Move the rest of the buffer to the beginning 160 | copy(buf, buf[frameSize+StdWriterPrefixLen:]) 161 | // Move the index 162 | nr -= frameSize + StdWriterPrefixLen 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/env.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "io" 11 | "strconv" 12 | "strings" 13 | ) 14 | 15 | // Env represents a list of key-pair represented in the form KEY=VALUE. 16 | type Env []string 17 | 18 | // Get returns the string value of the given key. 19 | func (env *Env) Get(key string) (value string) { 20 | return env.Map()[key] 21 | } 22 | 23 | // Exists checks whether the given key is defined in the internal Env 24 | // representation. 25 | func (env *Env) Exists(key string) bool { 26 | _, exists := env.Map()[key] 27 | return exists 28 | } 29 | 30 | // GetBool returns a boolean representation of the given key. The key is false 31 | // whenever its value if 0, no, false, none or an empty string. Any other value 32 | // will be interpreted as true. 33 | func (env *Env) GetBool(key string) (value bool) { 34 | s := strings.ToLower(strings.Trim(env.Get(key), " \t")) 35 | if s == "" || s == "0" || s == "no" || s == "false" || s == "none" { 36 | return false 37 | } 38 | return true 39 | } 40 | 41 | // SetBool defines a boolean value to the given key. 42 | func (env *Env) SetBool(key string, value bool) { 43 | if value { 44 | env.Set(key, "1") 45 | } else { 46 | env.Set(key, "0") 47 | } 48 | } 49 | 50 | // GetInt returns the value of the provided key, converted to int. 51 | // 52 | // It the value cannot be represented as an integer, it returns -1. 53 | func (env *Env) GetInt(key string) int { 54 | return int(env.GetInt64(key)) 55 | } 56 | 57 | // SetInt defines an integer value to the given key. 58 | func (env *Env) SetInt(key string, value int) { 59 | env.Set(key, strconv.Itoa(value)) 60 | } 61 | 62 | // GetInt64 returns the value of the provided key, converted to int64. 63 | // 64 | // It the value cannot be represented as an integer, it returns -1. 65 | func (env *Env) GetInt64(key string) int64 { 66 | s := strings.Trim(env.Get(key), " \t") 67 | val, err := strconv.ParseInt(s, 10, 64) 68 | if err != nil { 69 | return -1 70 | } 71 | return val 72 | } 73 | 74 | // SetInt64 defines an integer (64-bit wide) value to the given key. 75 | func (env *Env) SetInt64(key string, value int64) { 76 | env.Set(key, strconv.FormatInt(value, 10)) 77 | } 78 | 79 | // GetJSON unmarshals the value of the provided key in the provided iface. 80 | // 81 | // iface is a value that can be provided to the json.Unmarshal function. 82 | func (env *Env) GetJSON(key string, iface interface{}) error { 83 | sval := env.Get(key) 84 | if sval == "" { 85 | return nil 86 | } 87 | return json.Unmarshal([]byte(sval), iface) 88 | } 89 | 90 | // SetJSON marshals the given value to JSON format and stores it using the 91 | // provided key. 92 | func (env *Env) SetJSON(key string, value interface{}) error { 93 | sval, err := json.Marshal(value) 94 | if err != nil { 95 | return err 96 | } 97 | env.Set(key, string(sval)) 98 | return nil 99 | } 100 | 101 | // GetList returns a list of strings matching the provided key. It handles the 102 | // list as a JSON representation of a list of strings. 103 | // 104 | // If the given key matches to a single string, it will return a list 105 | // containing only the value that matches the key. 106 | func (env *Env) GetList(key string) []string { 107 | sval := env.Get(key) 108 | if sval == "" { 109 | return nil 110 | } 111 | var l []string 112 | if err := json.Unmarshal([]byte(sval), &l); err != nil { 113 | l = append(l, sval) 114 | } 115 | return l 116 | } 117 | 118 | // SetList stores the given list in the provided key, after serializing it to 119 | // JSON format. 120 | func (env *Env) SetList(key string, value []string) error { 121 | return env.SetJSON(key, value) 122 | } 123 | 124 | // Set defines the value of a key to the given string. 125 | func (env *Env) Set(key, value string) { 126 | *env = append(*env, key+"="+value) 127 | } 128 | 129 | // Decode decodes `src` as a json dictionary, and adds each decoded key-value 130 | // pair to the environment. 131 | // 132 | // If `src` cannot be decoded as a json dictionary, an error is returned. 133 | func (env *Env) Decode(src io.Reader) error { 134 | m := make(map[string]interface{}) 135 | if err := json.NewDecoder(src).Decode(&m); err != nil { 136 | return err 137 | } 138 | for k, v := range m { 139 | env.SetAuto(k, v) 140 | } 141 | return nil 142 | } 143 | 144 | // SetAuto will try to define the Set* method to call based on the given value. 145 | func (env *Env) SetAuto(key string, value interface{}) { 146 | if fval, ok := value.(float64); ok { 147 | env.SetInt64(key, int64(fval)) 148 | } else if sval, ok := value.(string); ok { 149 | env.Set(key, sval) 150 | } else if val, err := json.Marshal(value); err == nil { 151 | env.Set(key, string(val)) 152 | } else { 153 | env.Set(key, fmt.Sprintf("%v", value)) 154 | } 155 | } 156 | 157 | // Map returns the map representation of the env. 158 | func (env *Env) Map() map[string]string { 159 | if len(*env) == 0 { 160 | return nil 161 | } 162 | m := make(map[string]string) 163 | for _, kv := range *env { 164 | parts := strings.SplitN(kv, "=", 2) 165 | m[parts[0]] = parts[1] 166 | } 167 | return m 168 | } 169 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/opts/opts.go: -------------------------------------------------------------------------------- 1 | package opts 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "path/filepath" 8 | "regexp" 9 | "strings" 10 | 11 | "github.com/docker/docker/api" 12 | flag "github.com/docker/docker/pkg/mflag" 13 | "github.com/docker/docker/pkg/parsers" 14 | ) 15 | 16 | func ListVar(values *[]string, names []string, usage string) { 17 | flag.Var(newListOptsRef(values, nil), names, usage) 18 | } 19 | 20 | func HostListVar(values *[]string, names []string, usage string) { 21 | flag.Var(newListOptsRef(values, api.ValidateHost), names, usage) 22 | } 23 | 24 | func IPListVar(values *[]string, names []string, usage string) { 25 | flag.Var(newListOptsRef(values, ValidateIPAddress), names, usage) 26 | } 27 | 28 | func DnsSearchListVar(values *[]string, names []string, usage string) { 29 | flag.Var(newListOptsRef(values, ValidateDnsSearch), names, usage) 30 | } 31 | 32 | func IPVar(value *net.IP, names []string, defaultValue, usage string) { 33 | flag.Var(NewIpOpt(value, defaultValue), names, usage) 34 | } 35 | 36 | // ListOpts type 37 | type ListOpts struct { 38 | values *[]string 39 | validator ValidatorFctType 40 | } 41 | 42 | func NewListOpts(validator ValidatorFctType) ListOpts { 43 | var values []string 44 | return *newListOptsRef(&values, validator) 45 | } 46 | 47 | func newListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { 48 | return &ListOpts{ 49 | values: values, 50 | validator: validator, 51 | } 52 | } 53 | 54 | func (opts *ListOpts) String() string { 55 | return fmt.Sprintf("%v", []string((*opts.values))) 56 | } 57 | 58 | // Set validates if needed the input value and add it to the 59 | // internal slice. 60 | func (opts *ListOpts) Set(value string) error { 61 | if opts.validator != nil { 62 | v, err := opts.validator(value) 63 | if err != nil { 64 | return err 65 | } 66 | value = v 67 | } 68 | (*opts.values) = append((*opts.values), value) 69 | return nil 70 | } 71 | 72 | // Delete remove the given element from the slice. 73 | func (opts *ListOpts) Delete(key string) { 74 | for i, k := range *opts.values { 75 | if k == key { 76 | (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) 77 | return 78 | } 79 | } 80 | } 81 | 82 | // GetMap returns the content of values in a map in order to avoid 83 | // duplicates. 84 | // FIXME: can we remove this? 85 | func (opts *ListOpts) GetMap() map[string]struct{} { 86 | ret := make(map[string]struct{}) 87 | for _, k := range *opts.values { 88 | ret[k] = struct{}{} 89 | } 90 | return ret 91 | } 92 | 93 | // GetAll returns the values' slice. 94 | // FIXME: Can we remove this? 95 | func (opts *ListOpts) GetAll() []string { 96 | return (*opts.values) 97 | } 98 | 99 | // Get checks the existence of the given key. 100 | func (opts *ListOpts) Get(key string) bool { 101 | for _, k := range *opts.values { 102 | if k == key { 103 | return true 104 | } 105 | } 106 | return false 107 | } 108 | 109 | // Len returns the amount of element in the slice. 110 | func (opts *ListOpts) Len() int { 111 | return len((*opts.values)) 112 | } 113 | 114 | // Validators 115 | type ValidatorFctType func(val string) (string, error) 116 | 117 | func ValidateAttach(val string) (string, error) { 118 | s := strings.ToLower(val) 119 | for _, str := range []string{"stdin", "stdout", "stderr"} { 120 | if s == str { 121 | return s, nil 122 | } 123 | } 124 | return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR.") 125 | } 126 | 127 | func ValidateLink(val string) (string, error) { 128 | if _, err := parsers.PartParser("name:alias", val); err != nil { 129 | return val, err 130 | } 131 | return val, nil 132 | } 133 | 134 | func ValidatePath(val string) (string, error) { 135 | var containerPath string 136 | 137 | if strings.Count(val, ":") > 2 { 138 | return val, fmt.Errorf("bad format for volumes: %s", val) 139 | } 140 | 141 | splited := strings.SplitN(val, ":", 2) 142 | if len(splited) == 1 { 143 | containerPath = splited[0] 144 | val = filepath.Clean(splited[0]) 145 | } else { 146 | containerPath = splited[1] 147 | val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1])) 148 | } 149 | 150 | if !filepath.IsAbs(containerPath) { 151 | return val, fmt.Errorf("%s is not an absolute path", containerPath) 152 | } 153 | return val, nil 154 | } 155 | 156 | func ValidateEnv(val string) (string, error) { 157 | arr := strings.Split(val, "=") 158 | if len(arr) > 1 { 159 | return val, nil 160 | } 161 | return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil 162 | } 163 | 164 | func ValidateIPAddress(val string) (string, error) { 165 | var ip = net.ParseIP(strings.TrimSpace(val)) 166 | if ip != nil { 167 | return ip.String(), nil 168 | } 169 | return "", fmt.Errorf("%s is not an ip address", val) 170 | } 171 | 172 | // Validates domain for resolvconf search configuration. 173 | // A zero length domain is represented by . 174 | func ValidateDnsSearch(val string) (string, error) { 175 | if val = strings.Trim(val, " "); val == "." { 176 | return val, nil 177 | } 178 | return validateDomain(val) 179 | } 180 | 181 | func validateDomain(val string) (string, error) { 182 | alpha := regexp.MustCompile(`[a-zA-Z]`) 183 | if alpha.FindString(val) == "" { 184 | return "", fmt.Errorf("%s is not a valid domain", val) 185 | } 186 | re := regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`) 187 | ns := re.FindSubmatch([]byte(val)) 188 | if len(ns) > 0 { 189 | return string(ns[1]), nil 190 | } 191 | return "", fmt.Errorf("%s is not a valid domain", val) 192 | } 193 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/streams_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "strings" 10 | "testing" 11 | ) 12 | 13 | type sentinelWriteCloser struct { 14 | calledWrite bool 15 | calledClose bool 16 | } 17 | 18 | func (w *sentinelWriteCloser) Write(p []byte) (int, error) { 19 | w.calledWrite = true 20 | return len(p), nil 21 | } 22 | 23 | func (w *sentinelWriteCloser) Close() error { 24 | w.calledClose = true 25 | return nil 26 | } 27 | 28 | func TestOutputAddEnv(t *testing.T) { 29 | input := "{\"foo\": \"bar\", \"answer_to_life_the_universe_and_everything\": 42}" 30 | o := NewOutput() 31 | result, err := o.AddEnv() 32 | if err != nil { 33 | t.Fatal(err) 34 | } 35 | o.Write([]byte(input)) 36 | o.Close() 37 | if v := result.Get("foo"); v != "bar" { 38 | t.Errorf("Expected %v, got %v", "bar", v) 39 | } 40 | if v := result.GetInt("answer_to_life_the_universe_and_everything"); v != 42 { 41 | t.Errorf("Expected %v, got %v", 42, v) 42 | } 43 | if v := result.Get("this-value-doesnt-exist"); v != "" { 44 | t.Errorf("Expected %v, got %v", "", v) 45 | } 46 | } 47 | 48 | func TestOutputAddClose(t *testing.T) { 49 | o := NewOutput() 50 | var s sentinelWriteCloser 51 | o.Add(&s) 52 | if err := o.Close(); err != nil { 53 | t.Fatal(err) 54 | } 55 | // Write data after the output is closed. 56 | // Write should succeed, but no destination should receive it. 57 | if _, err := o.Write([]byte("foo bar")); err != nil { 58 | t.Fatal(err) 59 | } 60 | if !s.calledClose { 61 | t.Fatal("Output.Close() didn't close the destination") 62 | } 63 | } 64 | 65 | func TestOutputAddPipe(t *testing.T) { 66 | var testInputs = []string{ 67 | "hello, world!", 68 | "One\nTwo\nThree", 69 | "", 70 | "A line\nThen another nl-terminated line\n", 71 | "A line followed by an empty line\n\n", 72 | } 73 | for _, input := range testInputs { 74 | expectedOutput := input 75 | o := NewOutput() 76 | r, err := o.AddPipe() 77 | if err != nil { 78 | t.Fatal(err) 79 | } 80 | go func(o *Output) { 81 | if n, err := o.Write([]byte(input)); err != nil { 82 | t.Error(err) 83 | } else if n != len(input) { 84 | t.Errorf("Expected %d, got %d", len(input), n) 85 | } 86 | if err := o.Close(); err != nil { 87 | t.Error(err) 88 | } 89 | }(o) 90 | output, err := ioutil.ReadAll(r) 91 | if err != nil { 92 | t.Fatal(err) 93 | } 94 | if string(output) != expectedOutput { 95 | t.Errorf("Last line is not stored as return string.\nExpected: '%s'\nGot: '%s'", expectedOutput, output) 96 | } 97 | } 98 | } 99 | 100 | func TestTail(t *testing.T) { 101 | var tests = make(map[string][]string) 102 | tests["hello, world!"] = []string{ 103 | "", 104 | "hello, world!", 105 | "hello, world!", 106 | "hello, world!", 107 | } 108 | tests["One\nTwo\nThree"] = []string{ 109 | "", 110 | "Three", 111 | "Two\nThree", 112 | "One\nTwo\nThree", 113 | } 114 | for input, outputs := range tests { 115 | for n, expectedOutput := range outputs { 116 | output := Tail(bytes.NewBufferString(input), n) 117 | if output != expectedOutput { 118 | t.Errorf("Tail n=%d returned wrong result.\nExpected: '%s'\nGot : '%s'", n, expectedOutput, output) 119 | } 120 | } 121 | } 122 | } 123 | 124 | func lastLine(txt string) string { 125 | scanner := bufio.NewScanner(strings.NewReader(txt)) 126 | var lastLine string 127 | for scanner.Scan() { 128 | lastLine = scanner.Text() 129 | } 130 | return lastLine 131 | } 132 | 133 | func TestOutputAdd(t *testing.T) { 134 | o := NewOutput() 135 | b := &bytes.Buffer{} 136 | o.Add(b) 137 | input := "hello, world!" 138 | if n, err := o.Write([]byte(input)); err != nil { 139 | t.Fatal(err) 140 | } else if n != len(input) { 141 | t.Fatalf("Expected %d, got %d", len(input), n) 142 | } 143 | if output := b.String(); output != input { 144 | t.Fatalf("Received wrong data from Add.\nExpected: '%s'\nGot: '%s'", input, output) 145 | } 146 | } 147 | 148 | func TestOutputWriteError(t *testing.T) { 149 | o := NewOutput() 150 | buf := &bytes.Buffer{} 151 | o.Add(buf) 152 | r, w := io.Pipe() 153 | input := "Hello there" 154 | expectedErr := fmt.Errorf("This is an error") 155 | r.CloseWithError(expectedErr) 156 | o.Add(w) 157 | n, err := o.Write([]byte(input)) 158 | if err != expectedErr { 159 | t.Fatalf("Output.Write() should return the first error encountered, if any") 160 | } 161 | if buf.String() != input { 162 | t.Fatalf("Output.Write() should attempt write on all destinations, even after encountering an error") 163 | } 164 | if n != len(input) { 165 | t.Fatalf("Output.Write() should return the size of the input if it successfully writes to at least one destination") 166 | } 167 | } 168 | 169 | func TestInputAddEmpty(t *testing.T) { 170 | i := NewInput() 171 | var b bytes.Buffer 172 | if err := i.Add(&b); err != nil { 173 | t.Fatal(err) 174 | } 175 | data, err := ioutil.ReadAll(i) 176 | if err != nil { 177 | t.Fatal(err) 178 | } 179 | if len(data) > 0 { 180 | t.Fatalf("Read from empty input shoul yield no data") 181 | } 182 | } 183 | 184 | func TestInputAddTwo(t *testing.T) { 185 | i := NewInput() 186 | var b1 bytes.Buffer 187 | // First add should succeed 188 | if err := i.Add(&b1); err != nil { 189 | t.Fatal(err) 190 | } 191 | var b2 bytes.Buffer 192 | // Second add should fail 193 | if err := i.Add(&b2); err == nil { 194 | t.Fatalf("Adding a second source should return an error") 195 | } 196 | } 197 | 198 | func TestInputAddNotEmpty(t *testing.T) { 199 | i := NewInput() 200 | b := bytes.NewBufferString("hello world\nabc") 201 | expectedResult := b.String() 202 | i.Add(b) 203 | result, err := ioutil.ReadAll(i) 204 | if err != nil { 205 | t.Fatal(err) 206 | } 207 | if string(result) != expectedResult { 208 | t.Fatalf("Expected: %v\nReceived: %v", expectedResult, result) 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/streams.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "sync" 9 | ) 10 | 11 | type Output struct { 12 | sync.Mutex 13 | dests []io.Writer 14 | tasks sync.WaitGroup 15 | used bool 16 | } 17 | 18 | // Tail returns the n last lines of a buffer 19 | // stripped out of the last \n, if any 20 | // if n <= 0, returns an empty string 21 | func Tail(buffer *bytes.Buffer, n int) string { 22 | if n <= 0 { 23 | return "" 24 | } 25 | bytes := buffer.Bytes() 26 | if len(bytes) > 0 && bytes[len(bytes)-1] == '\n' { 27 | bytes = bytes[:len(bytes)-1] 28 | } 29 | for i := buffer.Len() - 2; i >= 0; i-- { 30 | if bytes[i] == '\n' { 31 | n-- 32 | if n == 0 { 33 | return string(bytes[i+1:]) 34 | } 35 | } 36 | } 37 | return string(bytes) 38 | } 39 | 40 | // NewOutput returns a new Output object with no destinations attached. 41 | // Writing to an empty Output will cause the written data to be discarded. 42 | func NewOutput() *Output { 43 | return &Output{} 44 | } 45 | 46 | // Return true if something was written on this output 47 | func (o *Output) Used() bool { 48 | o.Lock() 49 | defer o.Unlock() 50 | return o.used 51 | } 52 | 53 | // Add attaches a new destination to the Output. Any data subsequently written 54 | // to the output will be written to the new destination in addition to all the others. 55 | // This method is thread-safe. 56 | func (o *Output) Add(dst io.Writer) { 57 | o.Lock() 58 | defer o.Unlock() 59 | o.dests = append(o.dests, dst) 60 | } 61 | 62 | // Set closes and remove existing destination and then attaches a new destination to 63 | // the Output. Any data subsequently written to the output will be written to the new 64 | // destination in addition to all the others. This method is thread-safe. 65 | func (o *Output) Set(dst io.Writer) { 66 | o.Close() 67 | o.Lock() 68 | defer o.Unlock() 69 | o.dests = []io.Writer{dst} 70 | } 71 | 72 | // AddPipe creates an in-memory pipe with io.Pipe(), adds its writing end as a destination, 73 | // and returns its reading end for consumption by the caller. 74 | // This is a rough equivalent similar to Cmd.StdoutPipe() in the standard os/exec package. 75 | // This method is thread-safe. 76 | func (o *Output) AddPipe() (io.Reader, error) { 77 | r, w := io.Pipe() 78 | o.Add(w) 79 | return r, nil 80 | } 81 | 82 | // Write writes the same data to all registered destinations. 83 | // This method is thread-safe. 84 | func (o *Output) Write(p []byte) (n int, err error) { 85 | o.Lock() 86 | defer o.Unlock() 87 | o.used = true 88 | var firstErr error 89 | for _, dst := range o.dests { 90 | _, err := dst.Write(p) 91 | if err != nil && firstErr == nil { 92 | firstErr = err 93 | } 94 | } 95 | return len(p), firstErr 96 | } 97 | 98 | // Close unregisters all destinations and waits for all background 99 | // AddTail and AddString tasks to complete. 100 | // The Close method of each destination is called if it exists. 101 | func (o *Output) Close() error { 102 | o.Lock() 103 | defer o.Unlock() 104 | var firstErr error 105 | for _, dst := range o.dests { 106 | if closer, ok := dst.(io.Closer); ok { 107 | err := closer.Close() 108 | if err != nil && firstErr == nil { 109 | firstErr = err 110 | } 111 | } 112 | } 113 | o.tasks.Wait() 114 | return firstErr 115 | } 116 | 117 | type Input struct { 118 | src io.Reader 119 | sync.Mutex 120 | } 121 | 122 | // NewInput returns a new Input object with no source attached. 123 | // Reading to an empty Input will return io.EOF. 124 | func NewInput() *Input { 125 | return &Input{} 126 | } 127 | 128 | // Read reads from the input in a thread-safe way. 129 | func (i *Input) Read(p []byte) (n int, err error) { 130 | i.Mutex.Lock() 131 | defer i.Mutex.Unlock() 132 | if i.src == nil { 133 | return 0, io.EOF 134 | } 135 | return i.src.Read(p) 136 | } 137 | 138 | // Closes the src 139 | // Not thread safe on purpose 140 | func (i *Input) Close() error { 141 | if i.src != nil { 142 | if closer, ok := i.src.(io.Closer); ok { 143 | return closer.Close() 144 | } 145 | } 146 | return nil 147 | } 148 | 149 | // Add attaches a new source to the input. 150 | // Add can only be called once per input. Subsequent calls will 151 | // return an error. 152 | func (i *Input) Add(src io.Reader) error { 153 | i.Mutex.Lock() 154 | defer i.Mutex.Unlock() 155 | if i.src != nil { 156 | return fmt.Errorf("Maximum number of sources reached: 1") 157 | } 158 | i.src = src 159 | return nil 160 | } 161 | 162 | // AddEnv starts a new goroutine which will decode all subsequent data 163 | // as a stream of json-encoded objects, and point `dst` to the last 164 | // decoded object. 165 | // The result `env` can be queried using the type-neutral Env interface. 166 | // It is not safe to query `env` until the Output is closed. 167 | func (o *Output) AddEnv() (dst *Env, err error) { 168 | src, err := o.AddPipe() 169 | if err != nil { 170 | return nil, err 171 | } 172 | dst = &Env{} 173 | o.tasks.Add(1) 174 | go func() { 175 | defer o.tasks.Done() 176 | decoder := NewDecoder(src) 177 | for { 178 | env, err := decoder.Decode() 179 | if err != nil { 180 | return 181 | } 182 | *dst = *env 183 | } 184 | }() 185 | return dst, nil 186 | } 187 | 188 | func (o *Output) AddListTable() (dst *Table, err error) { 189 | src, err := o.AddPipe() 190 | if err != nil { 191 | return nil, err 192 | } 193 | dst = NewTable("", 0) 194 | o.tasks.Add(1) 195 | go func() { 196 | defer o.tasks.Done() 197 | content, err := ioutil.ReadAll(src) 198 | if err != nil { 199 | return 200 | } 201 | if _, err := dst.ReadListFrom(content); err != nil { 202 | return 203 | } 204 | }() 205 | return dst, nil 206 | } 207 | 208 | func (o *Output) AddTable() (dst *Table, err error) { 209 | src, err := o.AddPipe() 210 | if err != nil { 211 | return nil, err 212 | } 213 | dst = NewTable("", 0) 214 | o.tasks.Add(1) 215 | go func() { 216 | defer o.tasks.Done() 217 | if _, err := dst.ReadFrom(src); err != nil { 218 | return 219 | } 220 | }() 221 | return dst, nil 222 | } 223 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/job.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | // A job is the fundamental unit of work in the docker engine. 12 | // Everything docker can do should eventually be exposed as a job. 13 | // For example: execute a process in a container, create a new container, 14 | // download an archive from the internet, serve the http api, etc. 15 | // 16 | // The job API is designed after unix processes: a job has a name, arguments, 17 | // environment variables, standard streams for input, output and error, and 18 | // an exit status which can indicate success (0) or error (anything else). 19 | // 20 | // One slight variation is that jobs report their status as a string. The 21 | // string "0" indicates success, and any other strings indicates an error. 22 | // This allows for richer error reporting. 23 | // 24 | type Job struct { 25 | Eng *Engine 26 | Name string 27 | Args []string 28 | env *Env 29 | Stdout *Output 30 | Stderr *Output 31 | Stdin *Input 32 | handler Handler 33 | status Status 34 | end time.Time 35 | } 36 | 37 | type Status int 38 | 39 | const ( 40 | StatusOK Status = 0 41 | StatusErr Status = 1 42 | StatusNotFound Status = 127 43 | ) 44 | 45 | // Run executes the job and blocks until the job completes. 46 | // If the job returns a failure status, an error is returned 47 | // which includes the status. 48 | func (job *Job) Run() error { 49 | if job.Eng.IsShutdown() { 50 | return fmt.Errorf("engine is shutdown") 51 | } 52 | // FIXME: this is a temporary workaround to avoid Engine.Shutdown 53 | // waiting 5 seconds for server/api.ServeApi to complete (which it never will) 54 | // everytime the daemon is cleanly restarted. 55 | // The permanent fix is to implement Job.Stop and Job.OnStop so that 56 | // ServeApi can cooperate and terminate cleanly. 57 | if job.Name != "serveapi" { 58 | job.Eng.l.Lock() 59 | job.Eng.tasks.Add(1) 60 | job.Eng.l.Unlock() 61 | defer job.Eng.tasks.Done() 62 | } 63 | // FIXME: make this thread-safe 64 | // FIXME: implement wait 65 | if !job.end.IsZero() { 66 | return fmt.Errorf("%s: job has already completed", job.Name) 67 | } 68 | // Log beginning and end of the job 69 | job.Eng.Logf("+job %s", job.CallString()) 70 | defer func() { 71 | job.Eng.Logf("-job %s%s", job.CallString(), job.StatusString()) 72 | }() 73 | var errorMessage = bytes.NewBuffer(nil) 74 | job.Stderr.Add(errorMessage) 75 | if job.handler == nil { 76 | job.Errorf("%s: command not found", job.Name) 77 | job.status = 127 78 | } else { 79 | job.status = job.handler(job) 80 | job.end = time.Now() 81 | } 82 | // Wait for all background tasks to complete 83 | if err := job.Stdout.Close(); err != nil { 84 | return err 85 | } 86 | if err := job.Stderr.Close(); err != nil { 87 | return err 88 | } 89 | if err := job.Stdin.Close(); err != nil { 90 | return err 91 | } 92 | if job.status != 0 { 93 | return fmt.Errorf("%s", Tail(errorMessage, 1)) 94 | } 95 | return nil 96 | } 97 | 98 | func (job *Job) CallString() string { 99 | return fmt.Sprintf("%s(%s)", job.Name, strings.Join(job.Args, ", ")) 100 | } 101 | 102 | func (job *Job) StatusString() string { 103 | // If the job hasn't completed, status string is empty 104 | if job.end.IsZero() { 105 | return "" 106 | } 107 | var okerr string 108 | if job.status == StatusOK { 109 | okerr = "OK" 110 | } else { 111 | okerr = "ERR" 112 | } 113 | return fmt.Sprintf(" = %s (%d)", okerr, job.status) 114 | } 115 | 116 | // String returns a human-readable description of `job` 117 | func (job *Job) String() string { 118 | return fmt.Sprintf("%s.%s%s", job.Eng, job.CallString(), job.StatusString()) 119 | } 120 | 121 | func (job *Job) Env() *Env { 122 | return job.env 123 | } 124 | 125 | func (job *Job) EnvExists(key string) (value bool) { 126 | return job.env.Exists(key) 127 | } 128 | 129 | func (job *Job) Getenv(key string) (value string) { 130 | return job.env.Get(key) 131 | } 132 | 133 | func (job *Job) GetenvBool(key string) (value bool) { 134 | return job.env.GetBool(key) 135 | } 136 | 137 | func (job *Job) SetenvBool(key string, value bool) { 138 | job.env.SetBool(key, value) 139 | } 140 | 141 | func (job *Job) GetenvSubEnv(key string) *Env { 142 | return job.env.GetSubEnv(key) 143 | } 144 | 145 | func (job *Job) SetenvSubEnv(key string, value *Env) error { 146 | return job.env.SetSubEnv(key, value) 147 | } 148 | 149 | func (job *Job) GetenvInt64(key string) int64 { 150 | return job.env.GetInt64(key) 151 | } 152 | 153 | func (job *Job) GetenvInt(key string) int { 154 | return job.env.GetInt(key) 155 | } 156 | 157 | func (job *Job) SetenvInt64(key string, value int64) { 158 | job.env.SetInt64(key, value) 159 | } 160 | 161 | func (job *Job) SetenvInt(key string, value int) { 162 | job.env.SetInt(key, value) 163 | } 164 | 165 | // Returns nil if key not found 166 | func (job *Job) GetenvList(key string) []string { 167 | return job.env.GetList(key) 168 | } 169 | 170 | func (job *Job) GetenvJson(key string, iface interface{}) error { 171 | return job.env.GetJson(key, iface) 172 | } 173 | 174 | func (job *Job) SetenvJson(key string, value interface{}) error { 175 | return job.env.SetJson(key, value) 176 | } 177 | 178 | func (job *Job) SetenvList(key string, value []string) error { 179 | return job.env.SetJson(key, value) 180 | } 181 | 182 | func (job *Job) Setenv(key, value string) { 183 | job.env.Set(key, value) 184 | } 185 | 186 | // DecodeEnv decodes `src` as a json dictionary, and adds 187 | // each decoded key-value pair to the environment. 188 | // 189 | // If `src` cannot be decoded as a json dictionary, an error 190 | // is returned. 191 | func (job *Job) DecodeEnv(src io.Reader) error { 192 | return job.env.Decode(src) 193 | } 194 | 195 | func (job *Job) EncodeEnv(dst io.Writer) error { 196 | return job.env.Encode(dst) 197 | } 198 | 199 | func (job *Job) ImportEnv(src interface{}) (err error) { 200 | return job.env.Import(src) 201 | } 202 | 203 | func (job *Job) Environ() map[string]string { 204 | return job.env.Map() 205 | } 206 | 207 | func (job *Job) Logf(format string, args ...interface{}) (n int, err error) { 208 | prefixedFormat := fmt.Sprintf("[%s] %s\n", job, strings.TrimRight(format, "\n")) 209 | return fmt.Fprintf(job.Stderr, prefixedFormat, args...) 210 | } 211 | 212 | func (job *Job) Printf(format string, args ...interface{}) (n int, err error) { 213 | return fmt.Fprintf(job.Stdout, format, args...) 214 | } 215 | 216 | func (job *Job) Errorf(format string, args ...interface{}) Status { 217 | if format[len(format)-1] != '\n' { 218 | format = format + "\n" 219 | } 220 | fmt.Fprintf(job.Stderr, format, args...) 221 | return StatusErr 222 | } 223 | 224 | func (job *Job) Error(err error) Status { 225 | fmt.Fprintf(job.Stderr, "%s\n", err) 226 | return StatusErr 227 | } 228 | 229 | func (job *Job) StatusCode() int { 230 | return int(job.status) 231 | } 232 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/engine.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "os" 8 | "sort" 9 | "strings" 10 | "sync" 11 | "time" 12 | 13 | "github.com/docker/docker/utils" 14 | ) 15 | 16 | // Installer is a standard interface for objects which can "install" themselves 17 | // on an engine by registering handlers. 18 | // This can be used as an entrypoint for external plugins etc. 19 | type Installer interface { 20 | Install(*Engine) error 21 | } 22 | 23 | type Handler func(*Job) Status 24 | 25 | var globalHandlers map[string]Handler 26 | 27 | func init() { 28 | globalHandlers = make(map[string]Handler) 29 | } 30 | 31 | func Register(name string, handler Handler) error { 32 | _, exists := globalHandlers[name] 33 | if exists { 34 | return fmt.Errorf("Can't overwrite global handler for command %s", name) 35 | } 36 | globalHandlers[name] = handler 37 | return nil 38 | } 39 | 40 | func unregister(name string) { 41 | delete(globalHandlers, name) 42 | } 43 | 44 | // The Engine is the core of Docker. 45 | // It acts as a store for *containers*, and allows manipulation of these 46 | // containers by executing *jobs*. 47 | type Engine struct { 48 | handlers map[string]Handler 49 | catchall Handler 50 | hack Hack // data for temporary hackery (see hack.go) 51 | id string 52 | Stdout io.Writer 53 | Stderr io.Writer 54 | Stdin io.Reader 55 | Logging bool 56 | tasks sync.WaitGroup 57 | l sync.RWMutex // lock for shutdown 58 | shutdown bool 59 | onShutdown []func() // shutdown handlers 60 | } 61 | 62 | func (eng *Engine) Register(name string, handler Handler) error { 63 | _, exists := eng.handlers[name] 64 | if exists { 65 | return fmt.Errorf("Can't overwrite handler for command %s", name) 66 | } 67 | eng.handlers[name] = handler 68 | return nil 69 | } 70 | 71 | func (eng *Engine) RegisterCatchall(catchall Handler) { 72 | eng.catchall = catchall 73 | } 74 | 75 | // New initializes a new engine. 76 | func New() *Engine { 77 | eng := &Engine{ 78 | handlers: make(map[string]Handler), 79 | id: utils.RandomString(), 80 | Stdout: os.Stdout, 81 | Stderr: os.Stderr, 82 | Stdin: os.Stdin, 83 | Logging: true, 84 | } 85 | eng.Register("commands", func(job *Job) Status { 86 | for _, name := range eng.commands() { 87 | job.Printf("%s\n", name) 88 | } 89 | return StatusOK 90 | }) 91 | // Copy existing global handlers 92 | for k, v := range globalHandlers { 93 | eng.handlers[k] = v 94 | } 95 | return eng 96 | } 97 | 98 | func (eng *Engine) String() string { 99 | return fmt.Sprintf("%s", eng.id[:8]) 100 | } 101 | 102 | // Commands returns a list of all currently registered commands, 103 | // sorted alphabetically. 104 | func (eng *Engine) commands() []string { 105 | names := make([]string, 0, len(eng.handlers)) 106 | for name := range eng.handlers { 107 | names = append(names, name) 108 | } 109 | sort.Strings(names) 110 | return names 111 | } 112 | 113 | // Job creates a new job which can later be executed. 114 | // This function mimics `Command` from the standard os/exec package. 115 | func (eng *Engine) Job(name string, args ...string) *Job { 116 | job := &Job{ 117 | Eng: eng, 118 | Name: name, 119 | Args: args, 120 | Stdin: NewInput(), 121 | Stdout: NewOutput(), 122 | Stderr: NewOutput(), 123 | env: &Env{}, 124 | } 125 | if eng.Logging { 126 | job.Stderr.Add(utils.NopWriteCloser(eng.Stderr)) 127 | } 128 | 129 | // Catchall is shadowed by specific Register. 130 | if handler, exists := eng.handlers[name]; exists { 131 | job.handler = handler 132 | } else if eng.catchall != nil && name != "" { 133 | // empty job names are illegal, catchall or not. 134 | job.handler = eng.catchall 135 | } 136 | return job 137 | } 138 | 139 | // OnShutdown registers a new callback to be called by Shutdown. 140 | // This is typically used by services to perform cleanup. 141 | func (eng *Engine) OnShutdown(h func()) { 142 | eng.l.Lock() 143 | eng.onShutdown = append(eng.onShutdown, h) 144 | eng.l.Unlock() 145 | } 146 | 147 | // Shutdown permanently shuts down eng as follows: 148 | // - It refuses all new jobs, permanently. 149 | // - It waits for all active jobs to complete (with no timeout) 150 | // - It calls all shutdown handlers concurrently (if any) 151 | // - It returns when all handlers complete, or after 15 seconds, 152 | // whichever happens first. 153 | func (eng *Engine) Shutdown() { 154 | eng.l.Lock() 155 | if eng.shutdown { 156 | eng.l.Unlock() 157 | return 158 | } 159 | eng.shutdown = true 160 | eng.l.Unlock() 161 | // We don't need to protect the rest with a lock, to allow 162 | // for other calls to immediately fail with "shutdown" instead 163 | // of hanging for 15 seconds. 164 | // This requires all concurrent calls to check for shutdown, otherwise 165 | // it might cause a race. 166 | 167 | // Wait for all jobs to complete. 168 | // Timeout after 5 seconds. 169 | tasksDone := make(chan struct{}) 170 | go func() { 171 | eng.tasks.Wait() 172 | close(tasksDone) 173 | }() 174 | select { 175 | case <-time.After(time.Second * 5): 176 | case <-tasksDone: 177 | } 178 | 179 | // Call shutdown handlers, if any. 180 | // Timeout after 10 seconds. 181 | var wg sync.WaitGroup 182 | for _, h := range eng.onShutdown { 183 | wg.Add(1) 184 | go func(h func()) { 185 | defer wg.Done() 186 | h() 187 | }(h) 188 | } 189 | done := make(chan struct{}) 190 | go func() { 191 | wg.Wait() 192 | close(done) 193 | }() 194 | select { 195 | case <-time.After(time.Second * 10): 196 | case <-done: 197 | } 198 | return 199 | } 200 | 201 | // IsShutdown returns true if the engine is in the process 202 | // of shutting down, or already shut down. 203 | // Otherwise it returns false. 204 | func (eng *Engine) IsShutdown() bool { 205 | eng.l.RLock() 206 | defer eng.l.RUnlock() 207 | return eng.shutdown 208 | } 209 | 210 | // ParseJob creates a new job from a text description using a shell-like syntax. 211 | // 212 | // The following syntax is used to parse `input`: 213 | // 214 | // * Words are separated using standard whitespaces as separators. 215 | // * Quotes and backslashes are not interpreted. 216 | // * Words of the form 'KEY=[VALUE]' are added to the job environment. 217 | // * All other words are added to the job arguments. 218 | // 219 | // For example: 220 | // 221 | // job, _ := eng.ParseJob("VERBOSE=1 echo hello TEST=true world") 222 | // 223 | // The resulting job will have: 224 | // job.Args={"echo", "hello", "world"} 225 | // job.Env={"VERBOSE":"1", "TEST":"true"} 226 | // 227 | func (eng *Engine) ParseJob(input string) (*Job, error) { 228 | // FIXME: use a full-featured command parser 229 | scanner := bufio.NewScanner(strings.NewReader(input)) 230 | scanner.Split(bufio.ScanWords) 231 | var ( 232 | cmd []string 233 | env Env 234 | ) 235 | for scanner.Scan() { 236 | word := scanner.Text() 237 | kv := strings.SplitN(word, "=", 2) 238 | if len(kv) == 2 { 239 | env.Set(kv[0], kv[1]) 240 | } else { 241 | cmd = append(cmd, word) 242 | } 243 | } 244 | if len(cmd) == 0 { 245 | return nil, fmt.Errorf("empty command: '%s'", input) 246 | } 247 | job := eng.Job(cmd[0], cmd[1:]...) 248 | job.Env().Init(&env) 249 | return job, nil 250 | } 251 | 252 | func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) { 253 | if !eng.Logging { 254 | return 0, nil 255 | } 256 | prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n")) 257 | return fmt.Fprintf(eng.Stderr, prefixedFormat, args...) 258 | } 259 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/env.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | type Env []string 13 | 14 | func (env *Env) Get(key string) (value string) { 15 | // FIXME: use Map() 16 | for _, kv := range *env { 17 | if strings.Index(kv, "=") == -1 { 18 | continue 19 | } 20 | parts := strings.SplitN(kv, "=", 2) 21 | if parts[0] != key { 22 | continue 23 | } 24 | if len(parts) < 2 { 25 | value = "" 26 | } else { 27 | value = parts[1] 28 | } 29 | } 30 | return 31 | } 32 | 33 | func (env *Env) Exists(key string) bool { 34 | _, exists := env.Map()[key] 35 | return exists 36 | } 37 | 38 | // Len returns the number of keys in the environment. 39 | // Note that len(env) might be different from env.Len(), 40 | // because the same key might be set multiple times. 41 | func (env *Env) Len() int { 42 | return len(env.Map()) 43 | } 44 | 45 | func (env *Env) Init(src *Env) { 46 | (*env) = make([]string, 0, len(*src)) 47 | for _, val := range *src { 48 | (*env) = append((*env), val) 49 | } 50 | } 51 | 52 | func (env *Env) GetBool(key string) (value bool) { 53 | s := strings.ToLower(strings.Trim(env.Get(key), " \t")) 54 | if s == "" || s == "0" || s == "no" || s == "false" || s == "none" { 55 | return false 56 | } 57 | return true 58 | } 59 | 60 | func (env *Env) SetBool(key string, value bool) { 61 | if value { 62 | env.Set(key, "1") 63 | } else { 64 | env.Set(key, "0") 65 | } 66 | } 67 | 68 | func (env *Env) GetInt(key string) int { 69 | return int(env.GetInt64(key)) 70 | } 71 | 72 | func (env *Env) GetInt64(key string) int64 { 73 | s := strings.Trim(env.Get(key), " \t") 74 | val, err := strconv.ParseInt(s, 10, 64) 75 | if err != nil { 76 | return 0 77 | } 78 | return val 79 | } 80 | 81 | func (env *Env) SetInt(key string, value int) { 82 | env.Set(key, fmt.Sprintf("%d", value)) 83 | } 84 | 85 | func (env *Env) SetInt64(key string, value int64) { 86 | env.Set(key, fmt.Sprintf("%d", value)) 87 | } 88 | 89 | // Returns nil if key not found 90 | func (env *Env) GetList(key string) []string { 91 | sval := env.Get(key) 92 | if sval == "" { 93 | return nil 94 | } 95 | l := make([]string, 0, 1) 96 | if err := json.Unmarshal([]byte(sval), &l); err != nil { 97 | l = append(l, sval) 98 | } 99 | return l 100 | } 101 | 102 | func (env *Env) GetSubEnv(key string) *Env { 103 | sval := env.Get(key) 104 | if sval == "" { 105 | return nil 106 | } 107 | buf := bytes.NewBufferString(sval) 108 | var sub Env 109 | if err := sub.Decode(buf); err != nil { 110 | return nil 111 | } 112 | return &sub 113 | } 114 | 115 | func (env *Env) SetSubEnv(key string, sub *Env) error { 116 | var buf bytes.Buffer 117 | if err := sub.Encode(&buf); err != nil { 118 | return err 119 | } 120 | env.Set(key, string(buf.Bytes())) 121 | return nil 122 | } 123 | 124 | func (env *Env) GetJson(key string, iface interface{}) error { 125 | sval := env.Get(key) 126 | if sval == "" { 127 | return nil 128 | } 129 | return json.Unmarshal([]byte(sval), iface) 130 | } 131 | 132 | func (env *Env) SetJson(key string, value interface{}) error { 133 | sval, err := json.Marshal(value) 134 | if err != nil { 135 | return err 136 | } 137 | env.Set(key, string(sval)) 138 | return nil 139 | } 140 | 141 | func (env *Env) SetList(key string, value []string) error { 142 | return env.SetJson(key, value) 143 | } 144 | 145 | func (env *Env) Set(key, value string) { 146 | *env = append(*env, key+"="+value) 147 | } 148 | 149 | func NewDecoder(src io.Reader) *Decoder { 150 | return &Decoder{ 151 | json.NewDecoder(src), 152 | } 153 | } 154 | 155 | type Decoder struct { 156 | *json.Decoder 157 | } 158 | 159 | func (decoder *Decoder) Decode() (*Env, error) { 160 | m := make(map[string]interface{}) 161 | if err := decoder.Decoder.Decode(&m); err != nil { 162 | return nil, err 163 | } 164 | env := &Env{} 165 | for key, value := range m { 166 | env.SetAuto(key, value) 167 | } 168 | return env, nil 169 | } 170 | 171 | // DecodeEnv decodes `src` as a json dictionary, and adds 172 | // each decoded key-value pair to the environment. 173 | // 174 | // If `src` cannot be decoded as a json dictionary, an error 175 | // is returned. 176 | func (env *Env) Decode(src io.Reader) error { 177 | m := make(map[string]interface{}) 178 | if err := json.NewDecoder(src).Decode(&m); err != nil { 179 | return err 180 | } 181 | for k, v := range m { 182 | env.SetAuto(k, v) 183 | } 184 | return nil 185 | } 186 | 187 | func (env *Env) SetAuto(k string, v interface{}) { 188 | // FIXME: we fix-convert float values to int, because 189 | // encoding/json decodes integers to float64, but cannot encode them back. 190 | // (See http://golang.org/src/pkg/encoding/json/decode.go#L46) 191 | if fval, ok := v.(float64); ok { 192 | env.SetInt64(k, int64(fval)) 193 | } else if sval, ok := v.(string); ok { 194 | env.Set(k, sval) 195 | } else if val, err := json.Marshal(v); err == nil { 196 | env.Set(k, string(val)) 197 | } else { 198 | env.Set(k, fmt.Sprintf("%v", v)) 199 | } 200 | } 201 | 202 | func changeFloats(v interface{}) interface{} { 203 | switch v := v.(type) { 204 | case float64: 205 | return int(v) 206 | case map[string]interface{}: 207 | for key, val := range v { 208 | v[key] = changeFloats(val) 209 | } 210 | case []interface{}: 211 | for idx, val := range v { 212 | v[idx] = changeFloats(val) 213 | } 214 | } 215 | return v 216 | } 217 | 218 | func (env *Env) Encode(dst io.Writer) error { 219 | m := make(map[string]interface{}) 220 | for k, v := range env.Map() { 221 | var val interface{} 222 | if err := json.Unmarshal([]byte(v), &val); err == nil { 223 | // FIXME: we fix-convert float values to int, because 224 | // encoding/json decodes integers to float64, but cannot encode them back. 225 | // (See http://golang.org/src/pkg/encoding/json/decode.go#L46) 226 | m[k] = changeFloats(val) 227 | } else { 228 | m[k] = v 229 | } 230 | } 231 | if err := json.NewEncoder(dst).Encode(&m); err != nil { 232 | return err 233 | } 234 | return nil 235 | } 236 | 237 | func (env *Env) WriteTo(dst io.Writer) (n int64, err error) { 238 | // FIXME: return the number of bytes written to respect io.WriterTo 239 | return 0, env.Encode(dst) 240 | } 241 | 242 | func (env *Env) Import(src interface{}) (err error) { 243 | defer func() { 244 | if err != nil { 245 | err = fmt.Errorf("ImportEnv: %s", err) 246 | } 247 | }() 248 | var buf bytes.Buffer 249 | if err := json.NewEncoder(&buf).Encode(src); err != nil { 250 | return err 251 | } 252 | if err := env.Decode(&buf); err != nil { 253 | return err 254 | } 255 | return nil 256 | } 257 | 258 | func (env *Env) Map() map[string]string { 259 | m := make(map[string]string) 260 | for _, kv := range *env { 261 | parts := strings.SplitN(kv, "=", 2) 262 | m[parts[0]] = parts[1] 263 | } 264 | return m 265 | } 266 | 267 | // MultiMap returns a representation of env as a 268 | // map of string arrays, keyed by string. 269 | // This is the same structure as http headers for example, 270 | // which allow each key to have multiple values. 271 | func (env *Env) MultiMap() map[string][]string { 272 | m := make(map[string][]string) 273 | for _, kv := range *env { 274 | parts := strings.SplitN(kv, "=", 2) 275 | m[parts[0]] = append(m[parts[0]], parts[1]) 276 | } 277 | return m 278 | } 279 | 280 | // InitMultiMap removes all values in env, then initializes 281 | // new values from the contents of m. 282 | func (env *Env) InitMultiMap(m map[string][]string) { 283 | (*env) = make([]string, 0, len(m)) 284 | for k, vals := range m { 285 | for _, v := range vals { 286 | env.Set(k, v) 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/engine/env_test.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "testing" 7 | 8 | "github.com/docker/docker/pkg/testutils" 9 | ) 10 | 11 | func TestEnvLenZero(t *testing.T) { 12 | env := &Env{} 13 | if env.Len() != 0 { 14 | t.Fatalf("%d", env.Len()) 15 | } 16 | } 17 | 18 | func TestEnvLenNotZero(t *testing.T) { 19 | env := &Env{} 20 | env.Set("foo", "bar") 21 | env.Set("ga", "bu") 22 | if env.Len() != 2 { 23 | t.Fatalf("%d", env.Len()) 24 | } 25 | } 26 | 27 | func TestEnvLenDup(t *testing.T) { 28 | env := &Env{ 29 | "foo=bar", 30 | "foo=baz", 31 | "a=b", 32 | } 33 | // len(env) != env.Len() 34 | if env.Len() != 2 { 35 | t.Fatalf("%d", env.Len()) 36 | } 37 | } 38 | 39 | func TestNewJob(t *testing.T) { 40 | job := mkJob(t, "dummy", "--level=awesome") 41 | if job.Name != "dummy" { 42 | t.Fatalf("Wrong job name: %s", job.Name) 43 | } 44 | if len(job.Args) != 1 { 45 | t.Fatalf("Wrong number of job arguments: %d", len(job.Args)) 46 | } 47 | if job.Args[0] != "--level=awesome" { 48 | t.Fatalf("Wrong job arguments: %s", job.Args[0]) 49 | } 50 | } 51 | 52 | func TestSetenv(t *testing.T) { 53 | job := mkJob(t, "dummy") 54 | job.Setenv("foo", "bar") 55 | if val := job.Getenv("foo"); val != "bar" { 56 | t.Fatalf("Getenv returns incorrect value: %s", val) 57 | } 58 | 59 | job.Setenv("bar", "") 60 | if val := job.Getenv("bar"); val != "" { 61 | t.Fatalf("Getenv returns incorrect value: %s", val) 62 | } 63 | if val := job.Getenv("nonexistent"); val != "" { 64 | t.Fatalf("Getenv returns incorrect value: %s", val) 65 | } 66 | } 67 | 68 | func TestSetenvBool(t *testing.T) { 69 | job := mkJob(t, "dummy") 70 | job.SetenvBool("foo", true) 71 | if val := job.GetenvBool("foo"); !val { 72 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 73 | } 74 | 75 | job.SetenvBool("bar", false) 76 | if val := job.GetenvBool("bar"); val { 77 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 78 | } 79 | 80 | if val := job.GetenvBool("nonexistent"); val { 81 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 82 | } 83 | } 84 | 85 | func TestSetenvInt(t *testing.T) { 86 | job := mkJob(t, "dummy") 87 | 88 | job.SetenvInt("foo", -42) 89 | if val := job.GetenvInt("foo"); val != -42 { 90 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 91 | } 92 | 93 | job.SetenvInt("bar", 42) 94 | if val := job.GetenvInt("bar"); val != 42 { 95 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 96 | } 97 | if val := job.GetenvInt("nonexistent"); val != 0 { 98 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 99 | } 100 | } 101 | 102 | func TestSetenvList(t *testing.T) { 103 | job := mkJob(t, "dummy") 104 | 105 | job.SetenvList("foo", []string{"bar"}) 106 | if val := job.GetenvList("foo"); len(val) != 1 || val[0] != "bar" { 107 | t.Fatalf("GetenvList returns incorrect value: %v", val) 108 | } 109 | 110 | job.SetenvList("bar", nil) 111 | if val := job.GetenvList("bar"); val != nil { 112 | t.Fatalf("GetenvList returns incorrect value: %v", val) 113 | } 114 | if val := job.GetenvList("nonexistent"); val != nil { 115 | t.Fatalf("GetenvList returns incorrect value: %v", val) 116 | } 117 | } 118 | 119 | func TestEnviron(t *testing.T) { 120 | job := mkJob(t, "dummy") 121 | job.Setenv("foo", "bar") 122 | val, exists := job.Environ()["foo"] 123 | if !exists { 124 | t.Fatalf("foo not found in the environ") 125 | } 126 | if val != "bar" { 127 | t.Fatalf("bar not found in the environ") 128 | } 129 | } 130 | 131 | func TestMultiMap(t *testing.T) { 132 | e := &Env{} 133 | e.Set("foo", "bar") 134 | e.Set("bar", "baz") 135 | e.Set("hello", "world") 136 | m := e.MultiMap() 137 | e2 := &Env{} 138 | e2.Set("old_key", "something something something") 139 | e2.InitMultiMap(m) 140 | if v := e2.Get("old_key"); v != "" { 141 | t.Fatalf("%#v", v) 142 | } 143 | if v := e2.Get("bar"); v != "baz" { 144 | t.Fatalf("%#v", v) 145 | } 146 | if v := e2.Get("hello"); v != "world" { 147 | t.Fatalf("%#v", v) 148 | } 149 | } 150 | 151 | func testMap(l int) [][2]string { 152 | res := make([][2]string, l) 153 | for i := 0; i < l; i++ { 154 | t := [2]string{testutils.RandomString(5), testutils.RandomString(20)} 155 | res[i] = t 156 | } 157 | return res 158 | } 159 | 160 | func BenchmarkSet(b *testing.B) { 161 | fix := testMap(100) 162 | b.ResetTimer() 163 | for i := 0; i < b.N; i++ { 164 | env := &Env{} 165 | for _, kv := range fix { 166 | env.Set(kv[0], kv[1]) 167 | } 168 | } 169 | } 170 | 171 | func BenchmarkSetJson(b *testing.B) { 172 | fix := testMap(100) 173 | type X struct { 174 | f string 175 | } 176 | b.ResetTimer() 177 | for i := 0; i < b.N; i++ { 178 | env := &Env{} 179 | for _, kv := range fix { 180 | if err := env.SetJson(kv[0], X{kv[1]}); err != nil { 181 | b.Fatal(err) 182 | } 183 | } 184 | } 185 | } 186 | 187 | func BenchmarkGet(b *testing.B) { 188 | fix := testMap(100) 189 | env := &Env{} 190 | for _, kv := range fix { 191 | env.Set(kv[0], kv[1]) 192 | } 193 | b.ResetTimer() 194 | for i := 0; i < b.N; i++ { 195 | for _, kv := range fix { 196 | env.Get(kv[0]) 197 | } 198 | } 199 | } 200 | 201 | func BenchmarkGetJson(b *testing.B) { 202 | fix := testMap(100) 203 | env := &Env{} 204 | type X struct { 205 | f string 206 | } 207 | for _, kv := range fix { 208 | env.SetJson(kv[0], X{kv[1]}) 209 | } 210 | b.ResetTimer() 211 | for i := 0; i < b.N; i++ { 212 | for _, kv := range fix { 213 | if err := env.GetJson(kv[0], &X{}); err != nil { 214 | b.Fatal(err) 215 | } 216 | } 217 | } 218 | } 219 | 220 | func BenchmarkEncode(b *testing.B) { 221 | fix := testMap(100) 222 | env := &Env{} 223 | type X struct { 224 | f string 225 | } 226 | // half a json 227 | for i, kv := range fix { 228 | if i%2 != 0 { 229 | if err := env.SetJson(kv[0], X{kv[1]}); err != nil { 230 | b.Fatal(err) 231 | } 232 | continue 233 | } 234 | env.Set(kv[0], kv[1]) 235 | } 236 | var writer bytes.Buffer 237 | b.ResetTimer() 238 | for i := 0; i < b.N; i++ { 239 | env.Encode(&writer) 240 | writer.Reset() 241 | } 242 | } 243 | 244 | func BenchmarkDecode(b *testing.B) { 245 | fix := testMap(100) 246 | env := &Env{} 247 | type X struct { 248 | f string 249 | } 250 | // half a json 251 | for i, kv := range fix { 252 | if i%2 != 0 { 253 | if err := env.SetJson(kv[0], X{kv[1]}); err != nil { 254 | b.Fatal(err) 255 | } 256 | continue 257 | } 258 | env.Set(kv[0], kv[1]) 259 | } 260 | var writer bytes.Buffer 261 | env.Encode(&writer) 262 | denv := &Env{} 263 | reader := bytes.NewReader(writer.Bytes()) 264 | b.ResetTimer() 265 | for i := 0; i < b.N; i++ { 266 | err := denv.Decode(reader) 267 | if err != nil { 268 | b.Fatal(err) 269 | } 270 | reader.Seek(0, 0) 271 | } 272 | } 273 | 274 | func TestLongNumbers(t *testing.T) { 275 | type T struct { 276 | TestNum int64 277 | } 278 | v := T{67108864} 279 | var buf bytes.Buffer 280 | e := &Env{} 281 | e.SetJson("Test", v) 282 | if err := e.Encode(&buf); err != nil { 283 | t.Fatal(err) 284 | } 285 | res := make(map[string]T) 286 | if err := json.Unmarshal(buf.Bytes(), &res); err != nil { 287 | t.Fatal(err) 288 | } 289 | if res["Test"].TestNum != v.TestNum { 290 | t.Fatalf("TestNum %d, expected %d", res["Test"].TestNum, v.TestNum) 291 | } 292 | } 293 | 294 | func TestLongNumbersArray(t *testing.T) { 295 | type T struct { 296 | TestNum []int64 297 | } 298 | v := T{[]int64{67108864}} 299 | var buf bytes.Buffer 300 | e := &Env{} 301 | e.SetJson("Test", v) 302 | if err := e.Encode(&buf); err != nil { 303 | t.Fatal(err) 304 | } 305 | res := make(map[string]T) 306 | if err := json.Unmarshal(buf.Bytes(), &res); err != nil { 307 | t.Fatal(err) 308 | } 309 | if res["Test"].TestNum[0] != v.TestNum[0] { 310 | t.Fatalf("TestNum %d, expected %d", res["Test"].TestNum, v.TestNum) 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "encoding/json" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "math" 13 | "net" 14 | "net/http" 15 | "net/http/httputil" 16 | "sync" 17 | "sync/atomic" 18 | "time" 19 | ) 20 | 21 | // APIEvents represents an event returned by the API. 22 | type APIEvents struct { 23 | Status string 24 | ID string 25 | From string 26 | Time int64 27 | } 28 | 29 | type eventMonitoringState struct { 30 | sync.RWMutex 31 | sync.WaitGroup 32 | enabled bool 33 | lastSeen *int64 34 | C chan *APIEvents 35 | errC chan error 36 | listeners []chan<- *APIEvents 37 | } 38 | 39 | const ( 40 | maxMonitorConnRetries = 5 41 | retryInitialWaitTime = 10. 42 | ) 43 | 44 | var ( 45 | // ErrNoListeners is the error returned when no listeners are available 46 | // to receive an event. 47 | ErrNoListeners = errors.New("no listeners present to receive event") 48 | 49 | // ErrListenerAlreadyExists is the error returned when the listerner already 50 | // exists. 51 | ErrListenerAlreadyExists = errors.New("listener already exists for docker events") 52 | ) 53 | 54 | // AddEventListener adds a new listener to container events in the Docker API. 55 | // 56 | // The parameter is a channel through which events will be sent. 57 | func (c *Client) AddEventListener(listener chan<- *APIEvents) error { 58 | var err error 59 | if !c.eventMonitor.isEnabled() { 60 | err = c.eventMonitor.enableEventMonitoring(c) 61 | if err != nil { 62 | return err 63 | } 64 | } 65 | err = c.eventMonitor.addListener(listener) 66 | if err != nil { 67 | return err 68 | } 69 | return nil 70 | } 71 | 72 | // RemoveEventListener removes a listener from the monitor. 73 | func (c *Client) RemoveEventListener(listener chan *APIEvents) error { 74 | err := c.eventMonitor.removeListener(listener) 75 | if err != nil { 76 | return err 77 | } 78 | if len(c.eventMonitor.listeners) == 0 { 79 | err = c.eventMonitor.disableEventMonitoring() 80 | if err != nil { 81 | return err 82 | } 83 | } 84 | return nil 85 | } 86 | 87 | func (eventState *eventMonitoringState) addListener(listener chan<- *APIEvents) error { 88 | eventState.Lock() 89 | defer eventState.Unlock() 90 | if listenerExists(listener, &eventState.listeners) { 91 | return ErrListenerAlreadyExists 92 | } 93 | eventState.Add(1) 94 | eventState.listeners = append(eventState.listeners, listener) 95 | return nil 96 | } 97 | 98 | func (eventState *eventMonitoringState) removeListener(listener chan<- *APIEvents) error { 99 | eventState.Lock() 100 | defer eventState.Unlock() 101 | if listenerExists(listener, &eventState.listeners) { 102 | var newListeners []chan<- *APIEvents 103 | for _, l := range eventState.listeners { 104 | if l != listener { 105 | newListeners = append(newListeners, l) 106 | } 107 | } 108 | eventState.listeners = newListeners 109 | eventState.Add(-1) 110 | } 111 | return nil 112 | } 113 | 114 | func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool { 115 | for _, b := range *list { 116 | if b == a { 117 | return true 118 | } 119 | } 120 | return false 121 | } 122 | 123 | func (eventState *eventMonitoringState) enableEventMonitoring(c *Client) error { 124 | eventState.Lock() 125 | defer eventState.Unlock() 126 | if !eventState.enabled { 127 | eventState.enabled = true 128 | var lastSeenDefault = int64(0) 129 | eventState.lastSeen = &lastSeenDefault 130 | eventState.C = make(chan *APIEvents, 100) 131 | eventState.errC = make(chan error, 1) 132 | go eventState.monitorEvents(c) 133 | } 134 | return nil 135 | } 136 | 137 | func (eventState *eventMonitoringState) disableEventMonitoring() error { 138 | eventState.Wait() 139 | eventState.Lock() 140 | defer eventState.Unlock() 141 | if eventState.enabled { 142 | eventState.enabled = false 143 | close(eventState.C) 144 | close(eventState.errC) 145 | } 146 | return nil 147 | } 148 | 149 | func (eventState *eventMonitoringState) monitorEvents(c *Client) { 150 | var err error 151 | for eventState.noListeners() { 152 | time.Sleep(10 * time.Millisecond) 153 | } 154 | if err = eventState.connectWithRetry(c); err != nil { 155 | eventState.terminate(err) 156 | } 157 | for eventState.isEnabled() { 158 | timeout := time.After(100 * time.Millisecond) 159 | select { 160 | case ev, ok := <-eventState.C: 161 | if !ok { 162 | return 163 | } 164 | go eventState.sendEvent(ev) 165 | go eventState.updateLastSeen(ev) 166 | case err = <-eventState.errC: 167 | if err == ErrNoListeners { 168 | eventState.terminate(nil) 169 | return 170 | } else if err != nil { 171 | defer func() { go eventState.monitorEvents(c) }() 172 | return 173 | } 174 | case <-timeout: 175 | continue 176 | } 177 | } 178 | } 179 | 180 | func (eventState *eventMonitoringState) connectWithRetry(c *Client) error { 181 | var retries int 182 | var err error 183 | for err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC); err != nil && retries < maxMonitorConnRetries; retries++ { 184 | waitTime := int64(retryInitialWaitTime * math.Pow(2, float64(retries))) 185 | time.Sleep(time.Duration(waitTime) * time.Millisecond) 186 | err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC) 187 | } 188 | return err 189 | } 190 | 191 | func (eventState *eventMonitoringState) noListeners() bool { 192 | eventState.RLock() 193 | defer eventState.RUnlock() 194 | return len(eventState.listeners) == 0 195 | } 196 | 197 | func (eventState *eventMonitoringState) isEnabled() bool { 198 | eventState.RLock() 199 | defer eventState.RUnlock() 200 | return eventState.enabled 201 | } 202 | 203 | func (eventState *eventMonitoringState) sendEvent(event *APIEvents) { 204 | eventState.RLock() 205 | defer eventState.RUnlock() 206 | eventState.Add(1) 207 | defer eventState.Done() 208 | if eventState.isEnabled() { 209 | if eventState.noListeners() { 210 | eventState.errC <- ErrNoListeners 211 | return 212 | } 213 | 214 | for _, listener := range eventState.listeners { 215 | listener <- event 216 | } 217 | } 218 | } 219 | 220 | func (eventState *eventMonitoringState) updateLastSeen(e *APIEvents) { 221 | eventState.Lock() 222 | defer eventState.Unlock() 223 | if atomic.LoadInt64(eventState.lastSeen) < e.Time { 224 | atomic.StoreInt64(eventState.lastSeen, e.Time) 225 | } 226 | } 227 | 228 | func (eventState *eventMonitoringState) terminate(err error) { 229 | eventState.disableEventMonitoring() 230 | } 231 | 232 | func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan chan error) error { 233 | uri := "/events" 234 | if startTime != 0 { 235 | uri += fmt.Sprintf("?since=%d", startTime) 236 | } 237 | protocol := c.endpointURL.Scheme 238 | address := c.endpointURL.Path 239 | if protocol != "unix" { 240 | protocol = "tcp" 241 | address = c.endpointURL.Host 242 | } 243 | dial, err := net.Dial(protocol, address) 244 | if err != nil { 245 | return err 246 | } 247 | conn := httputil.NewClientConn(dial, nil) 248 | req, err := http.NewRequest("GET", uri, nil) 249 | if err != nil { 250 | return err 251 | } 252 | res, err := conn.Do(req) 253 | if err != nil { 254 | return err 255 | } 256 | go func(res *http.Response, conn *httputil.ClientConn) { 257 | defer conn.Close() 258 | defer res.Body.Close() 259 | decoder := json.NewDecoder(res.Body) 260 | for { 261 | var event APIEvents 262 | if err = decoder.Decode(&event); err != nil { 263 | if err == io.EOF || err == io.ErrUnexpectedEOF { 264 | break 265 | } 266 | errChan <- err 267 | } 268 | if event.Time == 0 { 269 | continue 270 | } 271 | if !c.eventMonitor.isEnabled() { 272 | return 273 | } 274 | c.eventMonitor.C <- &event 275 | } 276 | }(res, conn) 277 | return nil 278 | } 279 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/json" 7 | "errors" 8 | "fmt" 9 | "io" 10 | "io/ioutil" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | "os" 15 | gosignal "os/signal" 16 | "strconv" 17 | "strings" 18 | "syscall" 19 | 20 | "github.com/docker/docker/api" 21 | "github.com/docker/docker/dockerversion" 22 | "github.com/docker/docker/engine" 23 | "github.com/docker/docker/pkg/log" 24 | "github.com/docker/docker/pkg/term" 25 | "github.com/docker/docker/registry" 26 | "github.com/docker/docker/utils" 27 | ) 28 | 29 | var ( 30 | ErrConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?") 31 | ) 32 | 33 | func (cli *DockerCli) HTTPClient() *http.Client { 34 | tr := &http.Transport{ 35 | TLSClientConfig: cli.tlsConfig, 36 | Dial: func(network, addr string) (net.Conn, error) { 37 | return net.Dial(cli.proto, cli.addr) 38 | }, 39 | } 40 | return &http.Client{Transport: tr} 41 | } 42 | 43 | func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) { 44 | params := bytes.NewBuffer(nil) 45 | if data != nil { 46 | if env, ok := data.(engine.Env); ok { 47 | if err := env.Encode(params); err != nil { 48 | return nil, -1, err 49 | } 50 | } else { 51 | buf, err := json.Marshal(data) 52 | if err != nil { 53 | return nil, -1, err 54 | } 55 | if _, err := params.Write(buf); err != nil { 56 | return nil, -1, err 57 | } 58 | } 59 | } 60 | 61 | req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params) 62 | if err != nil { 63 | return nil, -1, err 64 | } 65 | if passAuthInfo { 66 | cli.LoadConfigFile() 67 | // Resolve the Auth config relevant for this server 68 | authConfig := cli.configFile.ResolveAuthConfig(registry.IndexServerAddress()) 69 | getHeaders := func(authConfig registry.AuthConfig) (map[string][]string, error) { 70 | buf, err := json.Marshal(authConfig) 71 | if err != nil { 72 | return nil, err 73 | } 74 | registryAuthHeader := []string{ 75 | base64.URLEncoding.EncodeToString(buf), 76 | } 77 | return map[string][]string{"X-Registry-Auth": registryAuthHeader}, nil 78 | } 79 | if headers, err := getHeaders(authConfig); err == nil && headers != nil { 80 | for k, v := range headers { 81 | req.Header[k] = v 82 | } 83 | } 84 | } 85 | req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) 86 | req.URL.Host = cli.addr 87 | req.URL.Scheme = cli.scheme 88 | if data != nil { 89 | req.Header.Set("Content-Type", "application/json") 90 | } else if method == "POST" { 91 | req.Header.Set("Content-Type", "plain/text") 92 | } 93 | resp, err := cli.HTTPClient().Do(req) 94 | if err != nil { 95 | if strings.Contains(err.Error(), "connection refused") { 96 | return nil, -1, ErrConnectionRefused 97 | } 98 | return nil, -1, err 99 | } 100 | 101 | if resp.StatusCode < 200 || resp.StatusCode >= 400 { 102 | body, err := ioutil.ReadAll(resp.Body) 103 | if err != nil { 104 | return nil, -1, err 105 | } 106 | if len(body) == 0 { 107 | return nil, resp.StatusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(resp.StatusCode), req.URL) 108 | } 109 | return nil, resp.StatusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body)) 110 | } 111 | return resp.Body, resp.StatusCode, nil 112 | } 113 | 114 | func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, headers map[string][]string) error { 115 | return cli.streamHelper(method, path, true, in, out, nil, headers) 116 | } 117 | 118 | func (cli *DockerCli) streamHelper(method, path string, setRawTerminal bool, in io.Reader, stdout, stderr io.Writer, headers map[string][]string) error { 119 | if (method == "POST" || method == "PUT") && in == nil { 120 | in = bytes.NewReader([]byte{}) 121 | } 122 | 123 | req, err := http.NewRequest(method, fmt.Sprintf("http://v%s%s", api.APIVERSION, path), in) 124 | if err != nil { 125 | return err 126 | } 127 | req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) 128 | req.URL.Host = cli.addr 129 | req.URL.Scheme = cli.scheme 130 | if method == "POST" { 131 | req.Header.Set("Content-Type", "plain/text") 132 | } 133 | 134 | if headers != nil { 135 | for k, v := range headers { 136 | req.Header[k] = v 137 | } 138 | } 139 | resp, err := cli.HTTPClient().Do(req) 140 | if err != nil { 141 | if strings.Contains(err.Error(), "connection refused") { 142 | return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?") 143 | } 144 | return err 145 | } 146 | defer resp.Body.Close() 147 | 148 | if resp.StatusCode < 200 || resp.StatusCode >= 400 { 149 | body, err := ioutil.ReadAll(resp.Body) 150 | if err != nil { 151 | return err 152 | } 153 | if len(body) == 0 { 154 | return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode)) 155 | } 156 | return fmt.Errorf("Error: %s", bytes.TrimSpace(body)) 157 | } 158 | 159 | if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") { 160 | return utils.DisplayJSONMessagesStream(resp.Body, stdout, cli.terminalFd, cli.isTerminal) 161 | } 162 | if stdout != nil || stderr != nil { 163 | // When TTY is ON, use regular copy 164 | if setRawTerminal { 165 | _, err = io.Copy(stdout, resp.Body) 166 | } else { 167 | _, err = utils.StdCopy(stdout, stderr, resp.Body) 168 | } 169 | log.Debugf("[stream] End of stdout") 170 | return err 171 | } 172 | return nil 173 | } 174 | 175 | func (cli *DockerCli) resizeTty(id string) { 176 | height, width := cli.getTtySize() 177 | if height == 0 && width == 0 { 178 | return 179 | } 180 | v := url.Values{} 181 | v.Set("h", strconv.Itoa(height)) 182 | v.Set("w", strconv.Itoa(width)) 183 | if _, _, err := readBody(cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil, false)); err != nil { 184 | log.Debugf("Error resize: %s", err) 185 | } 186 | } 187 | 188 | func waitForExit(cli *DockerCli, containerId string) (int, error) { 189 | stream, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil, false) 190 | if err != nil { 191 | return -1, err 192 | } 193 | 194 | var out engine.Env 195 | if err := out.Decode(stream); err != nil { 196 | return -1, err 197 | } 198 | return out.GetInt("StatusCode"), nil 199 | } 200 | 201 | // getExitCode perform an inspect on the container. It returns 202 | // the running state and the exit code. 203 | func getExitCode(cli *DockerCli, containerId string) (bool, int, error) { 204 | steam, _, err := cli.call("GET", "/containers/"+containerId+"/json", nil, false) 205 | if err != nil { 206 | // If we can't connect, then the daemon probably died. 207 | if err != ErrConnectionRefused { 208 | return false, -1, err 209 | } 210 | return false, -1, nil 211 | } 212 | 213 | var result engine.Env 214 | if err := result.Decode(steam); err != nil { 215 | return false, -1, err 216 | } 217 | 218 | state := result.GetSubEnv("State") 219 | return state.GetBool("Running"), state.GetInt("ExitCode"), nil 220 | } 221 | 222 | func (cli *DockerCli) monitorTtySize(id string) error { 223 | cli.resizeTty(id) 224 | 225 | sigchan := make(chan os.Signal, 1) 226 | gosignal.Notify(sigchan, syscall.SIGWINCH) 227 | go func() { 228 | for _ = range sigchan { 229 | cli.resizeTty(id) 230 | } 231 | }() 232 | return nil 233 | } 234 | 235 | func (cli *DockerCli) getTtySize() (int, int) { 236 | if !cli.isTerminal { 237 | return 0, 0 238 | } 239 | ws, err := term.GetWinsize(cli.terminalFd) 240 | if err != nil { 241 | log.Debugf("Error getting size: %s", err) 242 | if ws == nil { 243 | return 0, 0 244 | } 245 | } 246 | return int(ws.Height), int(ws.Width) 247 | } 248 | 249 | func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) { 250 | if stream != nil { 251 | defer stream.Close() 252 | } 253 | if err != nil { 254 | return nil, statusCode, err 255 | } 256 | body, err := ioutil.ReadAll(stream) 257 | if err != nil { 258 | return nil, -1, err 259 | } 260 | return body, statusCode, nil 261 | } 262 | --------------------------------------------------------------------------------