image_manager_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package images
  14. import (
  15. "errors"
  16. "testing"
  17. "time"
  18. "github.com/stretchr/testify/assert"
  19. "k8s.io/kubernetes/pkg/api"
  20. "k8s.io/kubernetes/pkg/client/record"
  21. . "k8s.io/kubernetes/pkg/kubelet/container"
  22. ctest "k8s.io/kubernetes/pkg/kubelet/container/testing"
  23. "k8s.io/kubernetes/pkg/util/clock"
  24. "k8s.io/kubernetes/pkg/util/flowcontrol"
  25. )
  26. func TestParallelPuller(t *testing.T) {
  27. pod := &api.Pod{
  28. ObjectMeta: api.ObjectMeta{
  29. Name: "test_pod",
  30. Namespace: "test-ns",
  31. UID: "bar",
  32. ResourceVersion: "42",
  33. SelfLink: "/api/v1/pods/foo",
  34. }}
  35. cases := []struct {
  36. containerImage string
  37. policy api.PullPolicy
  38. calledFunctions []string
  39. inspectErr error
  40. pullerErr error
  41. expectedErr []error
  42. }{
  43. { // pull missing image
  44. containerImage: "missing_image",
  45. policy: api.PullIfNotPresent,
  46. calledFunctions: []string{"IsImagePresent", "PullImage"},
  47. inspectErr: nil,
  48. pullerErr: nil,
  49. expectedErr: []error{nil}},
  50. { // image present, dont pull
  51. containerImage: "present_image",
  52. policy: api.PullIfNotPresent,
  53. calledFunctions: []string{"IsImagePresent"},
  54. inspectErr: nil,
  55. pullerErr: nil,
  56. expectedErr: []error{nil, nil, nil}},
  57. // image present, pull it
  58. {containerImage: "present_image",
  59. policy: api.PullAlways,
  60. calledFunctions: []string{"IsImagePresent", "PullImage"},
  61. inspectErr: nil,
  62. pullerErr: nil,
  63. expectedErr: []error{nil, nil, nil}},
  64. // missing image, error PullNever
  65. {containerImage: "missing_image",
  66. policy: api.PullNever,
  67. calledFunctions: []string{"IsImagePresent"},
  68. inspectErr: nil,
  69. pullerErr: nil,
  70. expectedErr: []error{ErrImageNeverPull, ErrImageNeverPull, ErrImageNeverPull}},
  71. // missing image, unable to inspect
  72. {containerImage: "missing_image",
  73. policy: api.PullIfNotPresent,
  74. calledFunctions: []string{"IsImagePresent"},
  75. inspectErr: errors.New("unknown inspectError"),
  76. pullerErr: nil,
  77. expectedErr: []error{ErrImageInspect, ErrImageInspect, ErrImageInspect}},
  78. // missing image, unable to fetch
  79. {containerImage: "typo_image",
  80. policy: api.PullIfNotPresent,
  81. calledFunctions: []string{"IsImagePresent", "PullImage"},
  82. inspectErr: nil,
  83. pullerErr: errors.New("404"),
  84. expectedErr: []error{ErrImagePull, ErrImagePull, ErrImagePullBackOff, ErrImagePull, ErrImagePullBackOff, ErrImagePullBackOff}},
  85. }
  86. for i, c := range cases {
  87. container := &api.Container{
  88. Name: "container_name",
  89. Image: c.containerImage,
  90. ImagePullPolicy: c.policy,
  91. }
  92. backOff := flowcontrol.NewBackOff(time.Second, time.Minute)
  93. fakeClock := clock.NewFakeClock(time.Now())
  94. backOff.Clock = fakeClock
  95. fakeRuntime := &ctest.FakeRuntime{}
  96. fakeRecorder := &record.FakeRecorder{}
  97. puller := NewImageManager(fakeRecorder, fakeRuntime, backOff, false)
  98. fakeRuntime.ImageList = []Image{{ID: "present_image", Size: 1}}
  99. fakeRuntime.Err = c.pullerErr
  100. fakeRuntime.InspectErr = c.inspectErr
  101. for tick, expected := range c.expectedErr {
  102. fakeClock.Step(time.Second)
  103. err, _ := puller.EnsureImageExists(pod, container, nil)
  104. fakeRuntime.AssertCalls(c.calledFunctions)
  105. assert.Equal(t, expected, err, "in test %d tick=%d", i, tick)
  106. }
  107. }
  108. }
  109. func TestSerializedPuller(t *testing.T) {
  110. pod := &api.Pod{
  111. ObjectMeta: api.ObjectMeta{
  112. Name: "test_pod",
  113. Namespace: "test-ns",
  114. UID: "bar",
  115. ResourceVersion: "42",
  116. SelfLink: "/api/v1/pods/foo",
  117. }}
  118. cases := []struct {
  119. containerImage string
  120. policy api.PullPolicy
  121. calledFunctions []string
  122. inspectErr error
  123. pullerErr error
  124. expectedErr []error
  125. }{
  126. { // pull missing image
  127. containerImage: "missing_image",
  128. policy: api.PullIfNotPresent,
  129. calledFunctions: []string{"IsImagePresent", "PullImage"},
  130. inspectErr: nil,
  131. pullerErr: nil,
  132. expectedErr: []error{nil}},
  133. { // image present, don't pull
  134. containerImage: "present_image",
  135. policy: api.PullIfNotPresent,
  136. calledFunctions: []string{"IsImagePresent"},
  137. inspectErr: nil,
  138. pullerErr: nil,
  139. expectedErr: []error{nil, nil, nil}},
  140. // image present, pull it
  141. {containerImage: "present_image",
  142. policy: api.PullAlways,
  143. calledFunctions: []string{"IsImagePresent", "PullImage"},
  144. inspectErr: nil,
  145. pullerErr: nil,
  146. expectedErr: []error{nil, nil, nil}},
  147. // missing image, error PullNever
  148. {containerImage: "missing_image",
  149. policy: api.PullNever,
  150. calledFunctions: []string{"IsImagePresent"},
  151. inspectErr: nil,
  152. pullerErr: nil,
  153. expectedErr: []error{ErrImageNeverPull, ErrImageNeverPull, ErrImageNeverPull}},
  154. // missing image, unable to inspect
  155. {containerImage: "missing_image",
  156. policy: api.PullIfNotPresent,
  157. calledFunctions: []string{"IsImagePresent"},
  158. inspectErr: errors.New("unknown inspectError"),
  159. pullerErr: nil,
  160. expectedErr: []error{ErrImageInspect, ErrImageInspect, ErrImageInspect}},
  161. // missing image, unable to fetch
  162. {containerImage: "typo_image",
  163. policy: api.PullIfNotPresent,
  164. calledFunctions: []string{"IsImagePresent", "PullImage"},
  165. inspectErr: nil,
  166. pullerErr: errors.New("404"),
  167. expectedErr: []error{ErrImagePull, ErrImagePull, ErrImagePullBackOff, ErrImagePull, ErrImagePullBackOff, ErrImagePullBackOff}},
  168. }
  169. for i, c := range cases {
  170. container := &api.Container{
  171. Name: "container_name",
  172. Image: c.containerImage,
  173. ImagePullPolicy: c.policy,
  174. }
  175. backOff := flowcontrol.NewBackOff(time.Second, time.Minute)
  176. fakeClock := clock.NewFakeClock(time.Now())
  177. backOff.Clock = fakeClock
  178. fakeRuntime := &ctest.FakeRuntime{}
  179. fakeRecorder := &record.FakeRecorder{}
  180. puller := NewImageManager(fakeRecorder, fakeRuntime, backOff, true)
  181. fakeRuntime.ImageList = []Image{{ID: "present_image"}}
  182. fakeRuntime.Err = c.pullerErr
  183. fakeRuntime.InspectErr = c.inspectErr
  184. for tick, expected := range c.expectedErr {
  185. fakeClock.Step(time.Second)
  186. err, _ := puller.EnsureImageExists(pod, container, nil)
  187. fakeRuntime.AssertCalls(c.calledFunctions)
  188. assert.Equal(t, expected, err, "in test %d tick=%d", i, tick)
  189. }
  190. }
  191. }