client_test.go 6.5 KB

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