diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index a756b8a1b95..abd2ace18cf 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -289,7 +289,7 @@ func (kl *Kubelet) runContainer(pod *Pod, container *api.Container, podVolumes v ExposedPorts: exposedPorts, Hostname: container.Name, Image: container.Image, - Memory: uint64(container.Memory), + Memory: int64(container.Memory), CpuShares: int64(milliCPUToShares(container.CPU)), Volumes: volumes, WorkingDir: container.WorkingDir, diff --git a/third_party/src/github.com/fsouza/go-dockerclient/AUTHORS b/third_party/src/github.com/fsouza/go-dockerclient/AUTHORS index d42a14a8324..98ff17b948a 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/AUTHORS +++ b/third_party/src/github.com/fsouza/go-dockerclient/AUTHORS @@ -1,5 +1,6 @@ # This is the official list of go-dockerclient authors for copyright purposes. +Andreas Jaekle Andrews Medina Andy Goldstein Ben McCann @@ -8,6 +9,7 @@ Cheah Chu Yeow cheneydeng Ed Eric Anderson +Fabio Rehm Flavia Missi Francisco Souza Jari Kolehmainen @@ -15,6 +17,8 @@ Jason Wilder Jean-Baptiste Dalido Jeff Mitchell Jeffrey Hulten +Johan Euphrosine +Karan Misra Lucas Clemente Omeid Matten Paul Morie diff --git a/third_party/src/github.com/fsouza/go-dockerclient/README.markdown b/third_party/src/github.com/fsouza/go-dockerclient/README.markdown index 7b4e959e0a2..0b7e83c63da 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/README.markdown +++ b/third_party/src/github.com/fsouza/go-dockerclient/README.markdown @@ -11,27 +11,29 @@ For more details, check the [remote API documentation](http://docs.docker.io/en/ ## Example - package main +```go +package main - import ( - "fmt" - "github.com/fsouza/go-dockerclient" - ) +import ( + "fmt" + "github.com/fsouza/go-dockerclient" +) - func main() { - endpoint := "unix:///var/run/docker.sock" - client, _ := docker.NewClient(endpoint) - imgs, _ := client.ListImages(true) - for _, img := range imgs { - fmt.Println("ID: ", img.ID) - fmt.Println("RepoTags: ", img.RepoTags) - fmt.Println("Created: ", img.Created) - fmt.Println("Size: ", img.Size) - fmt.Println("VirtualSize: ", img.VirtualSize) - fmt.Println("ParentId: ", img.ParentId) - fmt.Println("Repository: ", img.Repository) - } - } +func main() { + endpoint := "unix:///var/run/docker.sock" + client, _ := docker.NewClient(endpoint) + imgs, _ := client.ListImages(true) + for _, img := range imgs { + fmt.Println("ID: ", img.ID) + fmt.Println("RepoTags: ", img.RepoTags) + fmt.Println("Created: ", img.Created) + fmt.Println("Size: ", img.Size) + fmt.Println("VirtualSize: ", img.VirtualSize) + fmt.Println("ParentId: ", img.ParentId) + fmt.Println("Repository: ", img.Repository) + } +} +``` ## Developing diff --git a/third_party/src/github.com/fsouza/go-dockerclient/client.go b/third_party/src/github.com/fsouza/go-dockerclient/client.go index 681b7bf7835..74c15072ec4 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/client.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/client.go @@ -21,7 +21,6 @@ import ( "reflect" "strconv" "strings" - "sync" "github.com/fsouza/go-dockerclient/utils" ) @@ -113,11 +112,11 @@ func (version ApiVersion) compare(other ApiVersion) int { // interaction with the API. type Client struct { SkipServerVersionCheck bool + HTTPClient *http.Client endpoint string endpointURL *url.URL eventMonitor *eventMonitoringState - client *http.Client requestedApiVersion ApiVersion serverApiVersion ApiVersion expectedApiVersion ApiVersion @@ -142,7 +141,6 @@ func NewVersionedClient(endpoint string, apiVersionString string) (*Client, erro if err != nil { return nil, err } - var requestedApiVersion ApiVersion if strings.Contains(apiVersionString, ".") { requestedApiVersion, err = NewApiVersion(apiVersionString) @@ -150,11 +148,10 @@ func NewVersionedClient(endpoint string, apiVersionString string) (*Client, erro return nil, err } } - return &Client{ + HTTPClient: http.DefaultClient, endpoint: endpoint, endpointURL: u, - client: http.DefaultClient, eventMonitor: new(eventMonitoringState), requestedApiVersion: requestedApiVersion, }, nil @@ -177,29 +174,6 @@ func (c *Client) checkApiVersion() error { return nil } -func parseApiVersionString(input string) (version uint16, err error) { - version = 0 - - if !strings.Contains(input, ".") { - return 0, fmt.Errorf("Unable to parse version '%s'", input) - } - - arr := strings.Split(input, ".") - - major, err := strconv.Atoi(arr[0]) - if err != nil { - return version, err - } - - minor, err := strconv.Atoi(arr[1]) - if err != nil { - return version, err - } - - version = uint16(major)<<8 | uint16(minor) - return version, nil -} - // Ping pings the docker server // // See http://goo.gl/stJENm for more details. @@ -223,13 +197,11 @@ func (c *Client) getServerApiVersionString() (version string, err error) { if status != http.StatusOK { return "", fmt.Errorf("Received unexpected status %d while trying to retrieve the server version", status) } - var versionResponse map[string]string err = json.Unmarshal(body, &versionResponse) if err != nil { return "", err } - version = versionResponse["ApiVersion"] return version, nil } @@ -243,14 +215,12 @@ func (c *Client) do(method, path string, data interface{}) ([]byte, int, error) } params = bytes.NewBuffer(buf) } - if path != "/version" && !c.SkipServerVersionCheck && c.expectedApiVersion == nil { err := c.checkApiVersion() if err != nil { return nil, -1, err } } - req, err := http.NewRequest(method, c.getURL(path), params) if err != nil { return nil, -1, err @@ -277,7 +247,7 @@ func (c *Client) do(method, path string, data interface{}) ([]byte, int, error) } defer clientconn.Close() } else { - resp, err = c.client.Do(req) + resp, err = c.HTTPClient.Do(req) } if err != nil { if strings.Contains(err.Error(), "connection refused") { @@ -335,7 +305,7 @@ func (c *Client) stream(method, path string, setRawTerminal bool, headers map[st resp, err = clientconn.Do(req) defer clientconn.Close() } else { - resp, err = c.client.Do(req) + resp, err = c.HTTPClient.Do(req) } if err != nil { if strings.Contains(err.Error(), "connection refused") { @@ -418,10 +388,10 @@ func (c *Client) hijack(method, path string, success chan struct{}, setRawTermin <-success } rwc, br := clientconn.Hijack() - var wg sync.WaitGroup - wg.Add(2) errs := make(chan error, 2) + exit := make(chan bool) go func() { + defer close(exit) var err error if setRawTerminal { _, err = io.Copy(stdout, br) @@ -429,7 +399,6 @@ func (c *Client) hijack(method, path string, success chan struct{}, setRawTermin _, err = utils.StdCopy(stdout, stderr, br) } errs <- err - wg.Done() }() go func() { var err error @@ -440,14 +409,9 @@ func (c *Client) hijack(method, path string, success chan struct{}, setRawTermin CloseWrite() error }).CloseWrite() errs <- err - wg.Done() }() - wg.Wait() - close(errs) - if err := <-errs; err != nil { - return err - } - return nil + <-exit + return <-errs } func (c *Client) getURL(path string) string { diff --git a/third_party/src/github.com/fsouza/go-dockerclient/client_test.go b/third_party/src/github.com/fsouza/go-dockerclient/client_test.go index 53edd6c24c0..e623263f90f 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/client_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/client_test.go @@ -24,10 +24,9 @@ func TestNewAPIClient(t *testing.T) { if client.endpoint != endpoint { t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint) } - if client.client != http.DefaultClient { - t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.client) + if client.HTTPClient != http.DefaultClient { + t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient) } - // test unix socket endpoints endpoint = "unix:///var/run/docker.sock" client, err = NewClient(endpoint) @@ -54,8 +53,8 @@ func TestNewVersionedClient(t *testing.T) { if client.endpoint != endpoint { t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint) } - if client.client != http.DefaultClient { - t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.client) + if client.HTTPClient != http.DefaultClient { + t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient) } if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.12" { t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.12", reqVersion) diff --git a/third_party/src/github.com/fsouza/go-dockerclient/container.go b/third_party/src/github.com/fsouza/go-dockerclient/container.go index 25e1fad5f67..ab2c873e80d 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/container.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/container.go @@ -158,8 +158,8 @@ type Config struct { Hostname string Domainname string User string - Memory uint64 - MemorySwap uint64 + Memory int64 + MemorySwap int64 CpuShares int64 AttachStdin bool AttachStdout bool @@ -297,7 +297,7 @@ type HostConfig struct { NetworkMode string } -// StartContainer starts a container, returning an errror in case of failure. +// StartContainer starts a container, returning an error in case of failure. // // See http://goo.gl/y5GZlE for more details. func (c *Client) StartContainer(id string, hostConfig *HostConfig) error { diff --git a/third_party/src/github.com/fsouza/go-dockerclient/container_test.go b/third_party/src/github.com/fsouza/go-dockerclient/container_test.go index fbe9d1f74b4..c027c92c4e0 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/container_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/container_test.go @@ -225,6 +225,88 @@ func TestInspectContainer(t *testing.T) { } } +func TestInspectContainerNegativeSwap(t *testing.T) { + jsonContainer := `{ + "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2", + "Created": "2013-05-07T14:51:42.087658+02:00", + "Path": "date", + "Args": [], + "Config": { + "Hostname": "4fa6e0f0c678", + "User": "", + "Memory": 17179869184, + "MemorySwap": -1, + "AttachStdin": false, + "AttachStdout": true, + "AttachStderr": true, + "PortSpecs": null, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": null, + "Cmd": [ + "date" + ], + "Image": "base", + "Volumes": {}, + "VolumesFrom": "" + }, + "State": { + "Running": false, + "Pid": 0, + "ExitCode": 0, + "StartedAt": "2013-05-07T14:51:42.087658+02:00", + "Ghost": false + }, + "Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", + "NetworkSettings": { + "IpAddress": "", + "IpPrefixLen": 0, + "Gateway": "", + "Bridge": "", + "PortMapping": null + }, + "SysInitPath": "/home/kitty/go/src/github.com/dotcloud/docker/bin/docker", + "ResolvConfPath": "/etc/resolv.conf", + "Volumes": {}, + "HostConfig": { + "Binds": null, + "ContainerIDFile": "", + "LxcConf": [], + "Privileged": false, + "PortBindings": { + "80/tcp": [ + { + "HostIp": "0.0.0.0", + "HostPort": "49153" + } + ] + }, + "Links": null, + "PublishAllPorts": false + } +}` + var expected Container + err := json.Unmarshal([]byte(jsonContainer), &expected) + if err != nil { + t.Fatal(err) + } + fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK} + client := newTestClient(fakeRT) + id := "4fa6e0f0c678" + container, err := client.InspectContainer(id) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(*container, expected) { + t.Errorf("InspectContainer(%q): Expected %#v. Got %#v.", id, expected, container) + } + expectedURL, _ := url.Parse(client.getURL("/containers/4fa6e0f0c678/json")) + if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path { + t.Errorf("InspectContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath) + } +} + func TestInspectContainerFailure(t *testing.T) { client := newTestClient(&FakeRoundTripper{message: "server error", status: 500}) expected := Error{Status: 500, Message: "server error"} @@ -1184,9 +1266,9 @@ func TestExportContainerViaUnixSocket(t *testing.T) { endpoint := "unix://" + tempSocket u, _ := parseEndpoint(endpoint) client := Client{ + HTTPClient: http.DefaultClient, endpoint: endpoint, endpointURL: u, - client: http.DefaultClient, SkipServerVersionCheck: true, } listening := make(chan string) diff --git a/third_party/src/github.com/fsouza/go-dockerclient/env.go b/third_party/src/github.com/fsouza/go-dockerclient/env.go new file mode 100644 index 00000000000..c5ecb2b4ba0 --- /dev/null +++ b/third_party/src/github.com/fsouza/go-dockerclient/env.go @@ -0,0 +1,137 @@ +// Copyright 2014 Docker authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package docker + +import ( + "encoding/json" + "fmt" + "io" + "strconv" + "strings" +) + +type Env []string + +func (env *Env) Get(key string) (value string) { + return env.Map()[key] +} + +func (env *Env) Exists(key string) bool { + _, exists := env.Map()[key] + return exists +} + +func (env *Env) GetBool(key string) (value bool) { + s := strings.ToLower(strings.Trim(env.Get(key), " \t")) + if s == "" || s == "0" || s == "no" || s == "false" || s == "none" { + return false + } + return true +} + +func (env *Env) SetBool(key string, value bool) { + if value { + env.Set(key, "1") + } else { + env.Set(key, "0") + } +} + +func (env *Env) GetInt(key string) int { + return int(env.GetInt64(key)) +} + +func (env *Env) SetInt(key string, value int) { + env.Set(key, strconv.Itoa(value)) +} + +func (env *Env) GetInt64(key string) int64 { + s := strings.Trim(env.Get(key), " \t") + val, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return -1 + } + return val +} + +func (env *Env) SetInt64(key string, value int64) { + env.Set(key, strconv.FormatInt(value, 10)) +} + +func (env *Env) GetJson(key string, iface interface{}) error { + sval := env.Get(key) + if sval == "" { + return nil + } + return json.Unmarshal([]byte(sval), iface) +} + +func (env *Env) SetJson(key string, value interface{}) error { + sval, err := json.Marshal(value) + if err != nil { + return err + } + env.Set(key, string(sval)) + return nil +} + +func (env *Env) GetList(key string) []string { + sval := env.Get(key) + if sval == "" { + return nil + } + var l []string + if err := json.Unmarshal([]byte(sval), &l); err != nil { + l = append(l, sval) + } + return l +} + +func (env *Env) SetList(key string, value []string) error { + return env.SetJson(key, value) +} + +func (env *Env) Set(key, value string) { + *env = append(*env, key+"="+value) +} + +// Decode decodes `src` as a json dictionary, and adds each decoded key-value +// pair to the environment. +// +// If `src` cannot be decoded as a json dictionary, an error is returned. +func (env *Env) Decode(src io.Reader) error { + m := make(map[string]interface{}) + if err := json.NewDecoder(src).Decode(&m); err != nil { + return err + } + for k, v := range m { + env.SetAuto(k, v) + } + return nil +} + +func (env *Env) SetAuto(k string, v interface{}) { + if fval, ok := v.(float64); ok { + env.SetInt64(k, int64(fval)) + } else if sval, ok := v.(string); ok { + env.Set(k, sval) + } else if val, err := json.Marshal(v); err == nil { + env.Set(k, string(val)) + } else { + env.Set(k, fmt.Sprintf("%v", v)) + } +} + +func (env *Env) Map() map[string]string { + if len(*env) == 0 { + return nil + } + m := make(map[string]string) + for _, kv := range *env { + parts := strings.SplitN(kv, "=", 2) + m[parts[0]] = parts[1] + } + return m +} diff --git a/third_party/src/github.com/fsouza/go-dockerclient/env_test.go b/third_party/src/github.com/fsouza/go-dockerclient/env_test.go new file mode 100644 index 00000000000..e7a821f81ea --- /dev/null +++ b/third_party/src/github.com/fsouza/go-dockerclient/env_test.go @@ -0,0 +1,349 @@ +// Copyright 2014 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the DOCKER-LICENSE file. + +package docker + +import ( + "bytes" + "errors" + "reflect" + "sort" + "testing" +) + +func TestGet(t *testing.T) { + var tests = []struct { + input []string + query string + expected string + }{ + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PATH", "/usr/bin:/bin"}, + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATH", "/usr/local"}, + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATHI", ""}, + {[]string{"WAT="}, "WAT", ""}, + } + for _, tt := range tests { + env := Env(tt.input) + got := env.Get(tt.query) + if got != tt.expected { + t.Errorf("Env.Get(%q): wrong result. Want %q. Got %q", tt.query, tt.expected, got) + } + } +} + +func TestExists(t *testing.T) { + var tests = []struct { + input []string + query string + expected bool + }{ + {[]string{"WAT=", "PYTHONPATH=/usr/local"}, "WAT", true}, + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATH", true}, + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATHI", false}, + } + for _, tt := range tests { + env := Env(tt.input) + got := env.Exists(tt.query) + if got != tt.expected { + t.Errorf("Env.Exists(%q): wrong result. Want %v. Got %v", tt.query, tt.expected, got) + } + } +} + +func TestGetBool(t *testing.T) { + var tests = []struct { + input string + expected bool + }{ + {"EMTPY_VAR", false}, {"ZERO_VAR", false}, {"NO_VAR", false}, + {"FALSE_VAR", false}, {"NONE_VAR", false}, {"TRUE_VAR", true}, + {"WAT", true}, {"PATH", true}, {"ONE_VAR", true}, {"NO_VAR_TAB", false}, + } + env := Env([]string{ + "EMPTY_VAR=", "ZERO_VAR=0", "NO_VAR=no", "FALSE_VAR=false", + "NONE_VAR=none", "TRUE_VAR=true", "WAT=wat", "PATH=/usr/bin:/bin", + "ONE_VAR=1", "NO_VAR_TAB=0 \t\t\t", + }) + for _, tt := range tests { + got := env.GetBool(tt.input) + if got != tt.expected { + t.Errorf("Env.GetBool(%q): wrong result. Want %v. Got %v.", tt.input, tt.expected, got) + } + } +} + +func TestSetBool(t *testing.T) { + var tests = []struct { + input bool + expected string + }{ + {true, "1"}, {false, "0"}, + } + for _, tt := range tests { + var env Env + env.SetBool("SOME", tt.input) + if got := env.Get("SOME"); got != tt.expected { + t.Errorf("Env.SetBool(%v): wrong result. Want %q. Got %q", tt.input, tt.expected, got) + } + } +} + +func TestGetInt(t *testing.T) { + var tests = []struct { + input string + expected int + }{ + {"NEGATIVE_INTEGER", -10}, {"NON_INTEGER", -1}, {"ONE", 1}, {"TWO", 2}, + } + env := Env([]string{"NEGATIVE_INTEGER=-10", "NON_INTEGER=wat", "ONE=1", "TWO=2"}) + for _, tt := range tests { + got := env.GetInt(tt.input) + if got != tt.expected { + t.Errorf("Env.GetInt(%q): wrong result. Want %d. Got %d", tt.input, tt.expected, got) + } + } +} + +func TestSetInt(t *testing.T) { + var tests = []struct { + input int + expected string + }{ + {10, "10"}, {13, "13"}, {7, "7"}, {33, "33"}, + {0, "0"}, {-34, "-34"}, + } + for _, tt := range tests { + var env Env + env.SetInt("SOME", tt.input) + if got := env.Get("SOME"); got != tt.expected { + t.Errorf("Env.SetBool(%d): wrong result. Want %q. Got %q", tt.input, tt.expected, got) + } + } +} + +func TestGetInt64(t *testing.T) { + var tests = []struct { + input string + expected int64 + }{ + {"NEGATIVE_INTEGER", -10}, {"NON_INTEGER", -1}, {"ONE", 1}, {"TWO", 2}, + } + env := Env([]string{"NEGATIVE_INTEGER=-10", "NON_INTEGER=wat", "ONE=1", "TWO=2"}) + for _, tt := range tests { + got := env.GetInt64(tt.input) + if got != tt.expected { + t.Errorf("Env.GetInt64(%q): wrong result. Want %d. Got %d", tt.input, tt.expected, got) + } + } +} + +func TestSetInt64(t *testing.T) { + var tests = []struct { + input int64 + expected string + }{ + {10, "10"}, {13, "13"}, {7, "7"}, {33, "33"}, + {0, "0"}, {-34, "-34"}, + } + for _, tt := range tests { + var env Env + env.SetInt64("SOME", tt.input) + if got := env.Get("SOME"); got != tt.expected { + t.Errorf("Env.SetBool(%d): wrong result. Want %q. Got %q", tt.input, tt.expected, got) + } + } +} + +func TestGetJson(t *testing.T) { + var p struct { + Name string `json:"name"` + Age int `json:"age"` + } + var env Env + env.Set("person", `{"name":"Gopher","age":5}`) + err := env.GetJson("person", &p) + if err != nil { + t.Error(err) + } + if p.Name != "Gopher" { + t.Errorf("Env.GetJson(%q): wrong name. Want %q. Got %q", "person", "Gopher", p.Name) + } + if p.Age != 5 { + t.Errorf("Env.GetJson(%q): wrong age. Want %d. Got %d", "person", 5, p.Age) + } +} + +func TestGetJsonAbsent(t *testing.T) { + var l []string + var env Env + err := env.GetJson("person", &l) + if err != nil { + t.Error(err) + } + if l != nil { + t.Errorf("Env.GetJson(): get unexpected list %v", l) + } +} + +func TestGetJsonFailure(t *testing.T) { + var p []string + var env Env + env.Set("list-person", `{"name":"Gopher","age":5}`) + err := env.GetJson("list-person", &p) + if err == nil { + t.Errorf("Env.GetJson(%q): got unexpected error.", "list-person") + } +} + +func TestSetJson(t *testing.T) { + var p1 = struct { + Name string `json:"name"` + Age int `json:"age"` + }{Name: "Gopher", Age: 5} + var env Env + err := env.SetJson("person", p1) + if err != nil { + t.Error(err) + } + var p2 struct { + Name string `json:"name"` + Age int `json:"age"` + } + err = env.GetJson("person", &p2) + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(p1, p2) { + t.Errorf("Env.SetJson(%q): wrong result. Want %v. Got %v", "person", p1, p2) + } +} + +func TestSetJsonFailure(t *testing.T) { + var env Env + err := env.SetJson("person", unmarshable{}) + if err == nil { + t.Error("Env.SetJson(): got unexpected error") + } + if env.Exists("person") { + t.Errorf("Env.SetJson(): should not define the key %q, but did", "person") + } +} + +func TestGetList(t *testing.T) { + var tests = []struct { + input string + expected []string + }{ + {"WAT=wat", []string{"wat"}}, + {`WAT=["wat","wet","wit","wot","wut"]`, []string{"wat", "wet", "wit", "wot", "wut"}}, + {"WAT=", nil}, + } + for _, tt := range tests { + env := Env([]string{tt.input}) + got := env.GetList("WAT") + if !reflect.DeepEqual(got, tt.expected) { + t.Errorf("Env.GetList(%q): wrong result. Want %v. Got %v", "WAT", tt.expected, got) + } + } +} + +func TestSetList(t *testing.T) { + list := []string{"a", "b", "c"} + var env Env + env.SetList("SOME", list) + if got := env.GetList("SOME"); !reflect.DeepEqual(got, list) { + t.Errorf("Env.SetList(%v): wrong result. Got %v", list, got) + } +} + +func TestSet(t *testing.T) { + var env Env + env.Set("PATH", "/home/bin:/bin") + env.Set("SOMETHING", "/usr/bin") + env.Set("PATH", "/bin") + if expected, got := "/usr/bin", env.Get("SOMETHING"); got != expected { + t.Errorf("Env.Set(%q): wrong result. Want %q. Got %q", expected, expected, got) + } + if expected, got := "/bin", env.Get("PATH"); got != expected { + t.Errorf("Env.Set(%q): wrong result. Want %q. Got %q", expected, expected, got) + } +} + +func TestDecode(t *testing.T) { + var tests = []struct { + input string + expectedOut []string + expectedErr string + }{ + { + `{"PATH":"/usr/bin:/bin","containers":54,"wat":["123","345"]}`, + []string{"PATH=/usr/bin:/bin", "containers=54", `wat=["123","345"]`}, + "", + }, + {"}}", nil, "invalid character '}' looking for beginning of value"}, + {`{}`, nil, ""}, + } + for _, tt := range tests { + var env Env + err := env.Decode(bytes.NewBufferString(tt.input)) + if tt.expectedErr == "" { + if err != nil { + t.Error(err) + } + } else if tt.expectedErr != err.Error() { + t.Errorf("Env.Decode(): invalid error. Want %q. Got %q.", tt.expectedErr, err) + } + got := []string(env) + sort.Strings(got) + sort.Strings(tt.expectedOut) + if !reflect.DeepEqual(got, tt.expectedOut) { + t.Errorf("Env.Decode(): wrong result. Want %v. Got %v.", tt.expectedOut, got) + } + } +} + +func TestSetAuto(t *testing.T) { + buf := bytes.NewBufferString("oi") + var tests = []struct { + input interface{} + expected string + }{ + {10, "10"}, + {10.3, "10"}, + {"oi", "oi"}, + {buf, "{}"}, + {unmarshable{}, "{}"}, + } + for _, tt := range tests { + var env Env + env.SetAuto("SOME", tt.input) + if got := env.Get("SOME"); got != tt.expected { + t.Errorf("Env.SetAuto(%v): wrong result. Want %q. Got %q", tt.input, tt.expected, got) + } + } +} + +func TestMap(t *testing.T) { + var tests = []struct { + input []string + expected map[string]string + }{ + {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, map[string]string{"PATH": "/usr/bin:/bin", "PYTHONPATH": "/usr/local"}}, + {nil, nil}, + } + for _, tt := range tests { + env := Env(tt.input) + got := env.Map() + if !reflect.DeepEqual(got, tt.expected) { + t.Errorf("Env.Map(): wrong result. Want %v. Got %v", tt.expected, got) + } + } +} + +type unmarshable struct { +} + +func (unmarshable) MarshalJSON() ([]byte, error) { + return nil, errors.New("cannot marshal") +} diff --git a/third_party/src/github.com/fsouza/go-dockerclient/event_test.go b/third_party/src/github.com/fsouza/go-dockerclient/event_test.go index bf498d3cf0e..cb54f4ae925 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/event_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/event_test.go @@ -53,7 +53,7 @@ func TestEventListeners(t *testing.T) { for { select { case msg := <-listener: - t.Logf("Received: %s", *msg) + t.Logf("Recieved: %s", *msg) count++ err = checkEvent(count, msg) if err != nil { diff --git a/third_party/src/github.com/fsouza/go-dockerclient/image_test.go b/third_party/src/github.com/fsouza/go-dockerclient/image_test.go index a2db84db155..12928b37c51 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/image_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/image_test.go @@ -21,9 +21,9 @@ func newTestClient(rt *FakeRoundTripper) Client { endpoint := "http://localhost:4243" u, _ := parseEndpoint("http://localhost:4243") client := Client{ + HTTPClient: &http.Client{Transport: rt}, endpoint: endpoint, endpointURL: u, - client: &http.Client{Transport: rt}, SkipServerVersionCheck: true, } return client diff --git a/third_party/src/github.com/fsouza/go-dockerclient/misc.go b/third_party/src/github.com/fsouza/go-dockerclient/misc.go index 1b9267e28a3..3d0e9c803df 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/misc.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/misc.go @@ -6,39 +6,32 @@ package docker import ( "bytes" - "io" - - "github.com/fsouza/go-dockerclient/engine" ) // Version returns version information about the docker server. // // See http://goo.gl/IqKNRE for more details. -func (c *Client) Version() (*engine.Env, error) { +func (c *Client) Version() (*Env, error) { body, _, err := c.do("GET", "/version", nil) if err != nil { return nil, err } - out := engine.NewOutput() - remoteVersion, err := out.AddEnv() - if err != nil { + var env Env + if err := env.Decode(bytes.NewReader(body)); err != nil { return nil, err } - if _, err := io.Copy(out, bytes.NewReader(body)); err != nil { - return nil, err - } - return remoteVersion, nil + return &env, nil } // Info returns system-wide information, like the number of running containers. // // See http://goo.gl/LOmySw for more details. -func (c *Client) Info() (*engine.Env, error) { +func (c *Client) Info() (*Env, error) { body, _, err := c.do("GET", "/info", nil) if err != nil { return nil, err } - var info engine.Env + var info Env err = info.Decode(bytes.NewReader(body)) if err != nil { return nil, err diff --git a/third_party/src/github.com/fsouza/go-dockerclient/misc_test.go b/third_party/src/github.com/fsouza/go-dockerclient/misc_test.go index 8cf283e565f..d8e9b58dc43 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/misc_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/misc_test.go @@ -10,8 +10,6 @@ import ( "reflect" "sort" "testing" - - "github.com/fsouza/go-dockerclient/engine" ) type DockerVersion struct { @@ -81,7 +79,7 @@ func TestInfo(t *testing.T) { }` fakeRT := FakeRoundTripper{message: body, status: http.StatusOK} client := newTestClient(&fakeRT) - expected := engine.Env{} + expected := Env{} expected.SetInt("Containers", 11) expected.SetInt("Images", 16) expected.SetBool("Debug", false) diff --git a/third_party/src/github.com/fsouza/go-dockerclient/testing/server.go b/third_party/src/github.com/fsouza/go-dockerclient/testing/server.go index d79fcd49234..03e6ca4c743 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/testing/server.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/testing/server.go @@ -170,6 +170,12 @@ func (s *DockerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +// Returns default http.Handler mux, it allows customHandlers to call the +// default behavior if wanted. +func (s *DockerServer) DefaultHandler() http.Handler { + return s.mux +} + func (s *DockerServer) handlerWrapper(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { for errorID, urlRegexp := range s.failures { @@ -218,6 +224,11 @@ func (s *DockerServer) listImages(w http.ResponseWriter, r *http.Request) { ID: image.ID, Created: image.Created.Unix(), } + for tag, id := range s.imgIDs { + if id == image.ID { + result[i].RepoTags = append(result[i].RepoTags, tag) + } + } } s.cMut.RUnlock() w.Header().Set("Content-Type", "application/json") @@ -563,8 +574,9 @@ func (s *DockerServer) pushImage(w http.ResponseWriter, r *http.Request) { func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] s.iMut.RLock() + var tag string if img, ok := s.imgIDs[id]; ok { - id = img + id, tag = img, id } s.iMut.RUnlock() _, index, err := s.findImageByID(id) @@ -577,6 +589,9 @@ func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) { defer s.iMut.Unlock() s.images[index] = s.images[len(s.images)-1] s.images = s.images[:len(s.images)-1] + if tag != "" { + delete(s.imgIDs, tag) + } } func (s *DockerServer) inspectImage(w http.ResponseWriter, r *http.Request) { diff --git a/third_party/src/github.com/fsouza/go-dockerclient/testing/server_test.go b/third_party/src/github.com/fsouza/go-dockerclient/testing/server_test.go index bbd4654fd6c..97c3687ec67 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/testing/server_test.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/testing/server_test.go @@ -780,7 +780,7 @@ func addImages(server *DockerServer, n int, repo bool) { func TestListImages(t *testing.T) { server := DockerServer{} - addImages(&server, 2, false) + addImages(&server, 2, true) server.buildMuxer() recorder := httptest.NewRecorder() request, _ := http.NewRequest("GET", "/images/json?all=1", nil) @@ -791,8 +791,9 @@ func TestListImages(t *testing.T) { expected := make([]docker.APIImages, 2) for i, image := range server.images { expected[i] = docker.APIImages{ - ID: image.ID, - Created: image.Created.Unix(), + ID: image.ID, + Created: image.Created.Unix(), + RepoTags: []string{"docker/python-" + image.ID}, } } var got []docker.APIImages @@ -826,7 +827,8 @@ func TestRemoveImageByName(t *testing.T) { addImages(&server, 1, true) server.buildMuxer() recorder := httptest.NewRecorder() - path := "/images/docker/python-" + server.images[0].ID + imgName := "docker/python-" + server.images[0].ID + path := "/images/" + imgName request, _ := http.NewRequest("DELETE", path, nil) server.ServeHTTP(recorder, request) if recorder.Code != http.StatusNoContent { @@ -835,6 +837,10 @@ func TestRemoveImageByName(t *testing.T) { if len(server.images) > 0 { t.Error("RemoveImage: did not remove the image.") } + _, ok := server.imgIDs[imgName] + if ok { + t.Error("RemoveImage: did not remove image tag name.") + } } func TestPrepareFailure(t *testing.T) { @@ -945,3 +951,14 @@ func TestPing(t *testing.T) { t.Errorf("Ping: Expected code %d, got: %d", http.StatusOK, recorder.Code) } } + +func TestDefaultHandler(t *testing.T) { + server, err := NewServer("127.0.0.1:0", nil, nil) + if err != nil { + t.Fatal(err) + } + defer server.listener.Close() + if server.mux != server.DefaultHandler() { + t.Fatalf("DefaultHandler: Expected to return server.mux, got: %#v", server.DefaultHandler()) + } +} diff --git a/third_party/src/github.com/fsouza/go-dockerclient/utils/stdcopy.go b/third_party/src/github.com/fsouza/go-dockerclient/utils/stdcopy.go index dec604ce489..ca502ecf573 100644 --- a/third_party/src/github.com/fsouza/go-dockerclient/utils/stdcopy.go +++ b/third_party/src/github.com/fsouza/go-dockerclient/utils/stdcopy.go @@ -109,7 +109,6 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) // Write on stderr out = dsterr default: - Debugf("Error selecting output fd: (%d)", buf[StdWriterFdIndex]) return 0, ErrInvalidStdHeader } @@ -119,7 +118,6 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) // Check if the buffer is big enough to read the frame. // Extend it if necessary. if frameSize+StdWriterPrefixLen > bufLen { - Debugf("Extending buffer cap.") buf = append(buf, make([]byte, frameSize+StdWriterPrefixLen-len(buf)+1)...) bufLen = len(buf) } @@ -135,7 +133,6 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) nr += nr2 break } else if er != nil { - Debugf("Error reading frame: %s", er) return 0, er } nr += nr2 @@ -151,12 +148,10 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) written += int64(nw) } if ew != nil { - Debugf("Error writing frame: %s", ew) return 0, ew } // If the frame has not been fully written: error if nw != frameSize { - Debugf("Error Short Write: (%d on %d)", nw, frameSize) return written, io.ErrShortWrite }