2016-09-06 14:46:37 -04:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestNewEnvClient(t *testing.T) {
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
t.Skip("skipping unix only test for windows")
|
|
|
|
}
|
|
|
|
cases := []struct {
|
|
|
|
envs map[string]string
|
|
|
|
expectedError string
|
|
|
|
expectedVersion string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
envs: map[string]string{},
|
|
|
|
expectedVersion: DefaultVersion,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_CERT_PATH": "invalid/path",
|
|
|
|
},
|
|
|
|
expectedError: "Could not load X509 key pair: open invalid/path/cert.pem: no such file or directory. Make sure the key is not encrypted",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_CERT_PATH": "testdata/",
|
|
|
|
},
|
|
|
|
expectedVersion: DefaultVersion,
|
|
|
|
},
|
2016-09-21 22:16:44 -04:00
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_CERT_PATH": "testdata/",
|
|
|
|
"DOCKER_TLS_VERIFY": "1",
|
|
|
|
},
|
|
|
|
expectedVersion: DefaultVersion,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_CERT_PATH": "testdata/",
|
|
|
|
"DOCKER_HOST": "https://notaunixsocket",
|
|
|
|
},
|
|
|
|
expectedVersion: DefaultVersion,
|
|
|
|
},
|
2016-09-06 14:46:37 -04:00
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_HOST": "host",
|
|
|
|
},
|
|
|
|
expectedError: "unable to parse docker host `host`",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_HOST": "invalid://url",
|
|
|
|
},
|
|
|
|
expectedVersion: DefaultVersion,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_API_VERSION": "anything",
|
|
|
|
},
|
|
|
|
expectedVersion: "anything",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
envs: map[string]string{
|
|
|
|
"DOCKER_API_VERSION": "1.22",
|
|
|
|
},
|
|
|
|
expectedVersion: "1.22",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
|
|
|
recoverEnvs := setupEnvs(t, c.envs)
|
|
|
|
apiclient, err := NewEnvClient()
|
|
|
|
if c.expectedError != "" {
|
2016-09-21 22:16:44 -04:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected an error for %v", c)
|
|
|
|
} else if err.Error() != c.expectedError {
|
2016-09-06 14:46:37 -04:00
|
|
|
t.Errorf("expected an error %s, got %s, for %v", c.expectedError, err.Error(), c)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
version := apiclient.ClientVersion()
|
|
|
|
if version != c.expectedVersion {
|
|
|
|
t.Errorf("expected %s, got %s, for %v", c.expectedVersion, version, c)
|
|
|
|
}
|
|
|
|
}
|
2016-09-21 22:16:44 -04:00
|
|
|
|
|
|
|
if c.envs["DOCKER_TLS_VERIFY"] != "" {
|
|
|
|
// pedantic checking that this is handled correctly
|
|
|
|
tr := apiclient.client.Transport.(*http.Transport)
|
|
|
|
if tr.TLSClientConfig == nil {
|
2016-12-20 06:14:41 -05:00
|
|
|
t.Error("no TLS config found when DOCKER_TLS_VERIFY enabled")
|
2016-09-21 22:16:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if tr.TLSClientConfig.InsecureSkipVerify {
|
2016-12-20 06:14:41 -05:00
|
|
|
t.Error("TLS verification should be enabled")
|
2016-09-21 22:16:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-06 14:46:37 -04:00
|
|
|
recoverEnvs(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupEnvs(t *testing.T, envs map[string]string) func(*testing.T) {
|
|
|
|
oldEnvs := map[string]string{}
|
|
|
|
for key, value := range envs {
|
|
|
|
oldEnv := os.Getenv(key)
|
|
|
|
oldEnvs[key] = oldEnv
|
|
|
|
err := os.Setenv(key, value)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return func(t *testing.T) {
|
|
|
|
for key, value := range oldEnvs {
|
|
|
|
err := os.Setenv(key, value)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetAPIPath(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
v string
|
|
|
|
p string
|
|
|
|
q url.Values
|
|
|
|
e string
|
|
|
|
}{
|
|
|
|
{"", "/containers/json", nil, "/containers/json"},
|
|
|
|
{"", "/containers/json", url.Values{}, "/containers/json"},
|
|
|
|
{"", "/containers/json", url.Values{"s": []string{"c"}}, "/containers/json?s=c"},
|
|
|
|
{"1.22", "/containers/json", nil, "/v1.22/containers/json"},
|
|
|
|
{"1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
|
|
|
|
{"1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
|
|
|
|
{"v1.22", "/containers/json", nil, "/v1.22/containers/json"},
|
|
|
|
{"v1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
|
|
|
|
{"v1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
|
|
|
|
{"v1.22", "/networks/kiwl$%^", nil, "/v1.22/networks/kiwl$%25%5E"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, cs := range cases {
|
|
|
|
c, err := NewClient("unix:///var/run/docker.sock", cs.v, nil, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
g := c.getAPIPath(cs.p, cs.q)
|
|
|
|
if g != cs.e {
|
|
|
|
t.Fatalf("Expected %s, got %s", cs.e, g)
|
|
|
|
}
|
2016-09-07 21:57:54 -04:00
|
|
|
|
|
|
|
err = c.Close()
|
|
|
|
if nil != err {
|
|
|
|
t.Fatalf("close client failed, error message: %s", err)
|
|
|
|
}
|
2016-09-06 14:46:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseHost(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
host string
|
|
|
|
proto string
|
|
|
|
addr string
|
|
|
|
base string
|
|
|
|
err bool
|
|
|
|
}{
|
|
|
|
{"", "", "", "", true},
|
|
|
|
{"foobar", "", "", "", true},
|
|
|
|
{"foo://bar", "foo", "bar", "", false},
|
|
|
|
{"tcp://localhost:2476", "tcp", "localhost:2476", "", false},
|
|
|
|
{"tcp://localhost:2476/path", "tcp", "localhost:2476", "/path", false},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, cs := range cases {
|
|
|
|
p, a, b, e := ParseHost(cs.host)
|
|
|
|
if cs.err && e == nil {
|
|
|
|
t.Fatalf("expected error, got nil")
|
|
|
|
}
|
|
|
|
if !cs.err && e != nil {
|
|
|
|
t.Fatal(e)
|
|
|
|
}
|
|
|
|
if cs.proto != p {
|
|
|
|
t.Fatalf("expected proto %s, got %s", cs.proto, p)
|
|
|
|
}
|
|
|
|
if cs.addr != a {
|
|
|
|
t.Fatalf("expected addr %s, got %s", cs.addr, a)
|
|
|
|
}
|
|
|
|
if cs.base != b {
|
|
|
|
t.Fatalf("expected base %s, got %s", cs.base, b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUpdateClientVersion(t *testing.T) {
|
|
|
|
client := &Client{
|
2016-09-08 23:44:25 -04:00
|
|
|
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
2016-09-06 14:46:37 -04:00
|
|
|
splitQuery := strings.Split(req.URL.Path, "/")
|
|
|
|
queryVersion := splitQuery[1]
|
|
|
|
b, err := json.Marshal(types.Version{
|
|
|
|
APIVersion: queryVersion,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
|
|
|
Body: ioutil.NopCloser(bytes.NewReader(b)),
|
|
|
|
}, nil
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
v string
|
|
|
|
}{
|
|
|
|
{"1.20"},
|
|
|
|
{"v1.21"},
|
|
|
|
{"1.22"},
|
|
|
|
{"v1.22"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, cs := range cases {
|
|
|
|
client.UpdateClientVersion(cs.v)
|
|
|
|
r, err := client.ServerVersion(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if strings.TrimPrefix(r.APIVersion, "v") != strings.TrimPrefix(cs.v, "v") {
|
|
|
|
t.Fatalf("Expected %s, got %s", cs.v, r.APIVersion)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewEnvClientSetsDefaultVersion(t *testing.T) {
|
|
|
|
// Unset environment variables
|
|
|
|
envVarKeys := []string{
|
|
|
|
"DOCKER_HOST",
|
|
|
|
"DOCKER_API_VERSION",
|
|
|
|
"DOCKER_TLS_VERIFY",
|
|
|
|
"DOCKER_CERT_PATH",
|
|
|
|
}
|
|
|
|
envVarValues := make(map[string]string)
|
|
|
|
for _, key := range envVarKeys {
|
|
|
|
envVarValues[key] = os.Getenv(key)
|
|
|
|
os.Setenv(key, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
client, err := NewEnvClient()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if client.version != DefaultVersion {
|
|
|
|
t.Fatalf("Expected %s, got %s", DefaultVersion, client.version)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := "1.22"
|
|
|
|
os.Setenv("DOCKER_API_VERSION", expected)
|
|
|
|
client, err = NewEnvClient()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if client.version != expected {
|
|
|
|
t.Fatalf("Expected %s, got %s", expected, client.version)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore environment variables
|
|
|
|
for _, key := range envVarKeys {
|
|
|
|
os.Setenv(key, envVarValues[key])
|
|
|
|
}
|
|
|
|
}
|