create_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. package container // import "github.com/docker/docker/integration/container"
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "testing"
  8. "time"
  9. "github.com/docker/docker/api/types"
  10. "github.com/docker/docker/api/types/container"
  11. "github.com/docker/docker/api/types/network"
  12. ctr "github.com/docker/docker/integration/internal/container"
  13. "github.com/docker/docker/oci"
  14. "gotest.tools/assert"
  15. is "gotest.tools/assert/cmp"
  16. "gotest.tools/poll"
  17. "gotest.tools/skip"
  18. )
  19. func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) {
  20. defer setupTest(t)()
  21. client := testEnv.APIClient()
  22. testCases := []struct {
  23. doc string
  24. image string
  25. expectedError string
  26. }{
  27. {
  28. doc: "image and tag",
  29. image: "test456:v1",
  30. expectedError: "No such image: test456:v1",
  31. },
  32. {
  33. doc: "image no tag",
  34. image: "test456",
  35. expectedError: "No such image: test456",
  36. },
  37. {
  38. doc: "digest",
  39. image: "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
  40. expectedError: "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
  41. },
  42. }
  43. for _, tc := range testCases {
  44. tc := tc
  45. t.Run(tc.doc, func(t *testing.T) {
  46. t.Parallel()
  47. _, err := client.ContainerCreate(context.Background(),
  48. &container.Config{Image: tc.image},
  49. &container.HostConfig{},
  50. &network.NetworkingConfig{},
  51. "",
  52. )
  53. assert.Check(t, is.ErrorContains(err, tc.expectedError))
  54. })
  55. }
  56. }
  57. func TestCreateWithInvalidEnv(t *testing.T) {
  58. defer setupTest(t)()
  59. client := testEnv.APIClient()
  60. testCases := []struct {
  61. env string
  62. expectedError string
  63. }{
  64. {
  65. env: "",
  66. expectedError: "invalid environment variable:",
  67. },
  68. {
  69. env: "=",
  70. expectedError: "invalid environment variable: =",
  71. },
  72. {
  73. env: "=foo",
  74. expectedError: "invalid environment variable: =foo",
  75. },
  76. }
  77. for index, tc := range testCases {
  78. tc := tc
  79. t.Run(strconv.Itoa(index), func(t *testing.T) {
  80. t.Parallel()
  81. _, err := client.ContainerCreate(context.Background(),
  82. &container.Config{
  83. Image: "busybox",
  84. Env: []string{tc.env},
  85. },
  86. &container.HostConfig{},
  87. &network.NetworkingConfig{},
  88. "",
  89. )
  90. assert.Check(t, is.ErrorContains(err, tc.expectedError))
  91. })
  92. }
  93. }
  94. // Test case for #30166 (target was not validated)
  95. func TestCreateTmpfsMountsTarget(t *testing.T) {
  96. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  97. defer setupTest(t)()
  98. client := testEnv.APIClient()
  99. testCases := []struct {
  100. target string
  101. expectedError string
  102. }{
  103. {
  104. target: ".",
  105. expectedError: "mount path must be absolute",
  106. },
  107. {
  108. target: "foo",
  109. expectedError: "mount path must be absolute",
  110. },
  111. {
  112. target: "/",
  113. expectedError: "destination can't be '/'",
  114. },
  115. {
  116. target: "//",
  117. expectedError: "destination can't be '/'",
  118. },
  119. }
  120. for _, tc := range testCases {
  121. _, err := client.ContainerCreate(context.Background(),
  122. &container.Config{
  123. Image: "busybox",
  124. },
  125. &container.HostConfig{
  126. Tmpfs: map[string]string{tc.target: ""},
  127. },
  128. &network.NetworkingConfig{},
  129. "",
  130. )
  131. assert.Check(t, is.ErrorContains(err, tc.expectedError))
  132. }
  133. }
  134. func TestCreateWithCustomMaskedPaths(t *testing.T) {
  135. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  136. defer setupTest(t)()
  137. client := testEnv.APIClient()
  138. ctx := context.Background()
  139. testCases := []struct {
  140. maskedPaths []string
  141. expected []string
  142. }{
  143. {
  144. maskedPaths: []string{},
  145. expected: []string{},
  146. },
  147. {
  148. maskedPaths: nil,
  149. expected: oci.DefaultSpec().Linux.MaskedPaths,
  150. },
  151. {
  152. maskedPaths: []string{"/proc/kcore", "/proc/keys"},
  153. expected: []string{"/proc/kcore", "/proc/keys"},
  154. },
  155. }
  156. checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
  157. _, b, err := client.ContainerInspectWithRaw(ctx, name, false)
  158. assert.NilError(t, err)
  159. var inspectJSON map[string]interface{}
  160. err = json.Unmarshal(b, &inspectJSON)
  161. assert.NilError(t, err)
  162. cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
  163. assert.Check(t, is.Equal(true, ok), name)
  164. maskedPaths, ok := cfg["MaskedPaths"].([]interface{})
  165. assert.Check(t, is.Equal(true, ok), name)
  166. mps := []string{}
  167. for _, mp := range maskedPaths {
  168. mps = append(mps, mp.(string))
  169. }
  170. assert.DeepEqual(t, expected, mps)
  171. }
  172. for i, tc := range testCases {
  173. name := fmt.Sprintf("create-masked-paths-%d", i)
  174. config := container.Config{
  175. Image: "busybox",
  176. Cmd: []string{"true"},
  177. }
  178. hc := container.HostConfig{}
  179. if tc.maskedPaths != nil {
  180. hc.MaskedPaths = tc.maskedPaths
  181. }
  182. // Create the container.
  183. c, err := client.ContainerCreate(context.Background(),
  184. &config,
  185. &hc,
  186. &network.NetworkingConfig{},
  187. name,
  188. )
  189. assert.NilError(t, err)
  190. checkInspect(t, ctx, name, tc.expected)
  191. // Start the container.
  192. err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
  193. assert.NilError(t, err)
  194. poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))
  195. checkInspect(t, ctx, name, tc.expected)
  196. }
  197. }
  198. func TestCreateWithCustomReadonlyPaths(t *testing.T) {
  199. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  200. defer setupTest(t)()
  201. client := testEnv.APIClient()
  202. ctx := context.Background()
  203. testCases := []struct {
  204. doc string
  205. readonlyPaths []string
  206. expected []string
  207. }{
  208. {
  209. readonlyPaths: []string{},
  210. expected: []string{},
  211. },
  212. {
  213. readonlyPaths: nil,
  214. expected: oci.DefaultSpec().Linux.ReadonlyPaths,
  215. },
  216. {
  217. readonlyPaths: []string{"/proc/asound", "/proc/bus"},
  218. expected: []string{"/proc/asound", "/proc/bus"},
  219. },
  220. }
  221. checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
  222. _, b, err := client.ContainerInspectWithRaw(ctx, name, false)
  223. assert.NilError(t, err)
  224. var inspectJSON map[string]interface{}
  225. err = json.Unmarshal(b, &inspectJSON)
  226. assert.NilError(t, err)
  227. cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
  228. assert.Check(t, is.Equal(true, ok), name)
  229. readonlyPaths, ok := cfg["ReadonlyPaths"].([]interface{})
  230. assert.Check(t, is.Equal(true, ok), name)
  231. rops := []string{}
  232. for _, rop := range readonlyPaths {
  233. rops = append(rops, rop.(string))
  234. }
  235. assert.DeepEqual(t, expected, rops)
  236. }
  237. for i, tc := range testCases {
  238. name := fmt.Sprintf("create-readonly-paths-%d", i)
  239. config := container.Config{
  240. Image: "busybox",
  241. Cmd: []string{"true"},
  242. }
  243. hc := container.HostConfig{}
  244. if tc.readonlyPaths != nil {
  245. hc.ReadonlyPaths = tc.readonlyPaths
  246. }
  247. // Create the container.
  248. c, err := client.ContainerCreate(context.Background(),
  249. &config,
  250. &hc,
  251. &network.NetworkingConfig{},
  252. name,
  253. )
  254. assert.NilError(t, err)
  255. checkInspect(t, ctx, name, tc.expected)
  256. // Start the container.
  257. err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
  258. assert.NilError(t, err)
  259. poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))
  260. checkInspect(t, ctx, name, tc.expected)
  261. }
  262. }