client_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package client
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io/ioutil"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "runtime"
  10. "strings"
  11. "testing"
  12. "github.com/docker/docker/api/types"
  13. "golang.org/x/net/context"
  14. )
  15. func TestNewEnvClient(t *testing.T) {
  16. if runtime.GOOS == "windows" {
  17. t.Skip("skipping unix only test for windows")
  18. }
  19. cases := []struct {
  20. envs map[string]string
  21. expectedError string
  22. expectedVersion string
  23. }{
  24. {
  25. envs: map[string]string{},
  26. expectedVersion: DefaultVersion,
  27. },
  28. {
  29. envs: map[string]string{
  30. "DOCKER_CERT_PATH": "invalid/path",
  31. },
  32. expectedError: "Could not load X509 key pair: open invalid/path/cert.pem: no such file or directory. Make sure the key is not encrypted",
  33. },
  34. {
  35. envs: map[string]string{
  36. "DOCKER_CERT_PATH": "testdata/",
  37. },
  38. expectedVersion: DefaultVersion,
  39. },
  40. {
  41. envs: map[string]string{
  42. "DOCKER_CERT_PATH": "testdata/",
  43. "DOCKER_TLS_VERIFY": "1",
  44. },
  45. expectedVersion: DefaultVersion,
  46. },
  47. {
  48. envs: map[string]string{
  49. "DOCKER_CERT_PATH": "testdata/",
  50. "DOCKER_HOST": "https://notaunixsocket",
  51. },
  52. expectedVersion: DefaultVersion,
  53. },
  54. {
  55. envs: map[string]string{
  56. "DOCKER_HOST": "host",
  57. },
  58. expectedError: "unable to parse docker host `host`",
  59. },
  60. {
  61. envs: map[string]string{
  62. "DOCKER_HOST": "invalid://url",
  63. },
  64. expectedVersion: DefaultVersion,
  65. },
  66. {
  67. envs: map[string]string{
  68. "DOCKER_API_VERSION": "anything",
  69. },
  70. expectedVersion: "anything",
  71. },
  72. {
  73. envs: map[string]string{
  74. "DOCKER_API_VERSION": "1.22",
  75. },
  76. expectedVersion: "1.22",
  77. },
  78. }
  79. for _, c := range cases {
  80. recoverEnvs := setupEnvs(t, c.envs)
  81. apiclient, err := NewEnvClient()
  82. if c.expectedError != "" {
  83. if err == nil {
  84. t.Errorf("expected an error for %v", c)
  85. } else if err.Error() != c.expectedError {
  86. t.Errorf("expected an error %s, got %s, for %v", c.expectedError, err.Error(), c)
  87. }
  88. } else {
  89. if err != nil {
  90. t.Error(err)
  91. }
  92. version := apiclient.ClientVersion()
  93. if version != c.expectedVersion {
  94. t.Errorf("expected %s, got %s, for %v", c.expectedVersion, version, c)
  95. }
  96. }
  97. if c.envs["DOCKER_TLS_VERIFY"] != "" {
  98. // pedantic checking that this is handled correctly
  99. tr := apiclient.client.Transport.(*http.Transport)
  100. if tr.TLSClientConfig == nil {
  101. t.Error("no tls config found when DOCKER_TLS_VERIFY enabled")
  102. }
  103. if tr.TLSClientConfig.InsecureSkipVerify {
  104. t.Error("tls verification should be enabled")
  105. }
  106. }
  107. recoverEnvs(t)
  108. }
  109. }
  110. func setupEnvs(t *testing.T, envs map[string]string) func(*testing.T) {
  111. oldEnvs := map[string]string{}
  112. for key, value := range envs {
  113. oldEnv := os.Getenv(key)
  114. oldEnvs[key] = oldEnv
  115. err := os.Setenv(key, value)
  116. if err != nil {
  117. t.Error(err)
  118. }
  119. }
  120. return func(t *testing.T) {
  121. for key, value := range oldEnvs {
  122. err := os.Setenv(key, value)
  123. if err != nil {
  124. t.Error(err)
  125. }
  126. }
  127. }
  128. }
  129. func TestGetAPIPath(t *testing.T) {
  130. cases := []struct {
  131. v string
  132. p string
  133. q url.Values
  134. e string
  135. }{
  136. {"", "/containers/json", nil, "/containers/json"},
  137. {"", "/containers/json", url.Values{}, "/containers/json"},
  138. {"", "/containers/json", url.Values{"s": []string{"c"}}, "/containers/json?s=c"},
  139. {"1.22", "/containers/json", nil, "/v1.22/containers/json"},
  140. {"1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
  141. {"1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
  142. {"v1.22", "/containers/json", nil, "/v1.22/containers/json"},
  143. {"v1.22", "/containers/json", url.Values{}, "/v1.22/containers/json"},
  144. {"v1.22", "/containers/json", url.Values{"s": []string{"c"}}, "/v1.22/containers/json?s=c"},
  145. {"v1.22", "/networks/kiwl$%^", nil, "/v1.22/networks/kiwl$%25%5E"},
  146. }
  147. for _, cs := range cases {
  148. c, err := NewClient("unix:///var/run/docker.sock", cs.v, nil, nil)
  149. if err != nil {
  150. t.Fatal(err)
  151. }
  152. g := c.getAPIPath(cs.p, cs.q)
  153. if g != cs.e {
  154. t.Fatalf("Expected %s, got %s", cs.e, g)
  155. }
  156. err = c.Close()
  157. if nil != err {
  158. t.Fatalf("close client failed, error message: %s", err)
  159. }
  160. }
  161. }
  162. func TestParseHost(t *testing.T) {
  163. cases := []struct {
  164. host string
  165. proto string
  166. addr string
  167. base string
  168. err bool
  169. }{
  170. {"", "", "", "", true},
  171. {"foobar", "", "", "", true},
  172. {"foo://bar", "foo", "bar", "", false},
  173. {"tcp://localhost:2476", "tcp", "localhost:2476", "", false},
  174. {"tcp://localhost:2476/path", "tcp", "localhost:2476", "/path", false},
  175. }
  176. for _, cs := range cases {
  177. p, a, b, e := ParseHost(cs.host)
  178. if cs.err && e == nil {
  179. t.Fatalf("expected error, got nil")
  180. }
  181. if !cs.err && e != nil {
  182. t.Fatal(e)
  183. }
  184. if cs.proto != p {
  185. t.Fatalf("expected proto %s, got %s", cs.proto, p)
  186. }
  187. if cs.addr != a {
  188. t.Fatalf("expected addr %s, got %s", cs.addr, a)
  189. }
  190. if cs.base != b {
  191. t.Fatalf("expected base %s, got %s", cs.base, b)
  192. }
  193. }
  194. }
  195. func TestUpdateClientVersion(t *testing.T) {
  196. client := &Client{
  197. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  198. splitQuery := strings.Split(req.URL.Path, "/")
  199. queryVersion := splitQuery[1]
  200. b, err := json.Marshal(types.Version{
  201. APIVersion: queryVersion,
  202. })
  203. if err != nil {
  204. return nil, err
  205. }
  206. return &http.Response{
  207. StatusCode: http.StatusOK,
  208. Body: ioutil.NopCloser(bytes.NewReader(b)),
  209. }, nil
  210. }),
  211. }
  212. cases := []struct {
  213. v string
  214. }{
  215. {"1.20"},
  216. {"v1.21"},
  217. {"1.22"},
  218. {"v1.22"},
  219. }
  220. for _, cs := range cases {
  221. client.UpdateClientVersion(cs.v)
  222. r, err := client.ServerVersion(context.Background())
  223. if err != nil {
  224. t.Fatal(err)
  225. }
  226. if strings.TrimPrefix(r.APIVersion, "v") != strings.TrimPrefix(cs.v, "v") {
  227. t.Fatalf("Expected %s, got %s", cs.v, r.APIVersion)
  228. }
  229. }
  230. }
  231. func TestNewEnvClientSetsDefaultVersion(t *testing.T) {
  232. // Unset environment variables
  233. envVarKeys := []string{
  234. "DOCKER_HOST",
  235. "DOCKER_API_VERSION",
  236. "DOCKER_TLS_VERIFY",
  237. "DOCKER_CERT_PATH",
  238. }
  239. envVarValues := make(map[string]string)
  240. for _, key := range envVarKeys {
  241. envVarValues[key] = os.Getenv(key)
  242. os.Setenv(key, "")
  243. }
  244. client, err := NewEnvClient()
  245. if err != nil {
  246. t.Fatal(err)
  247. }
  248. if client.version != DefaultVersion {
  249. t.Fatalf("Expected %s, got %s", DefaultVersion, client.version)
  250. }
  251. expected := "1.22"
  252. os.Setenv("DOCKER_API_VERSION", expected)
  253. client, err = NewEnvClient()
  254. if err != nil {
  255. t.Fatal(err)
  256. }
  257. if client.version != expected {
  258. t.Fatalf("Expected %s, got %s", expected, client.version)
  259. }
  260. // Restore environment variables
  261. for _, key := range envVarKeys {
  262. os.Setenv(key, envVarValues[key])
  263. }
  264. }