mirror of https://github.com/k3s-io/k3s
third_party: update go-dockerclient
math.MaxInt64 represents 8 exabytes, which is a good limit for memory. Also, this is the type used by Docker, so it's not possible to get any value bigger than math.MaxInt64 as memory limit (both ram and swap) on a Docker container. Relevant discussion at #589 (more precisely, https://github.com/GoogleCloudPlatform/kubernetes/pull/589#issuecomment-50640605).pull/6/head
parent
dc6fdc423d
commit
2a345ffa9e
|
@ -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,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# This is the official list of go-dockerclient authors for copyright purposes.
|
||||
|
||||
Andreas Jaekle <andreas@jaekle.net>
|
||||
Andrews Medina <andrewsmedina@gmail.com>
|
||||
Andy Goldstein <andy.goldstein@redhat.com>
|
||||
Ben McCann <benmccann.com>
|
||||
|
@ -8,6 +9,7 @@ Cheah Chu Yeow <chuyeow@gmail.com>
|
|||
cheneydeng <cheneydeng@qq.com>
|
||||
Ed <edrocksit@gmail.com>
|
||||
Eric Anderson <anderson@copperegg.com>
|
||||
Fabio Rehm <fgrehm@gmail.com>
|
||||
Flavia Missi <flaviamissi@gmail.com>
|
||||
Francisco Souza <f@souza.cc>
|
||||
Jari Kolehmainen <jari.kolehmainen@digia.com>
|
||||
|
@ -15,6 +17,8 @@ Jason Wilder <jwilder@litl.com>
|
|||
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
||||
Jeff Mitchell <jeffrey.mitchell@gmail.com>
|
||||
Jeffrey Hulten <jhulten@gmail.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
Karan Misra <kidoman@gmail.com>
|
||||
Lucas Clemente <lucas@clemente.io>
|
||||
Omeid Matten <public@omeid.me>
|
||||
Paul Morie <pmorie@gmail.com>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 <nil> 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 <nil> 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")
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue