fake_runtime.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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 testing
  14. import (
  15. "context"
  16. "fmt"
  17. "io"
  18. "net/url"
  19. "reflect"
  20. "sync"
  21. "time"
  22. "k8s.io/api/core/v1"
  23. "k8s.io/apimachinery/pkg/types"
  24. "k8s.io/client-go/util/flowcontrol"
  25. runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
  26. . "k8s.io/kubernetes/pkg/kubelet/container"
  27. "k8s.io/kubernetes/pkg/volume"
  28. )
  29. type FakePod struct {
  30. Pod *Pod
  31. NetnsPath string
  32. }
  33. // FakeRuntime is a fake container runtime for testing.
  34. type FakeRuntime struct {
  35. sync.Mutex
  36. CalledFunctions []string
  37. PodList []*FakePod
  38. AllPodList []*FakePod
  39. ImageList []Image
  40. APIPodStatus v1.PodStatus
  41. PodStatus PodStatus
  42. StartedPods []string
  43. KilledPods []string
  44. StartedContainers []string
  45. KilledContainers []string
  46. RuntimeStatus *RuntimeStatus
  47. VersionInfo string
  48. APIVersionInfo string
  49. RuntimeType string
  50. Err error
  51. InspectErr error
  52. StatusErr error
  53. }
  54. const FakeHost = "localhost:12345"
  55. type FakeStreamingRuntime struct {
  56. *FakeRuntime
  57. }
  58. var _ StreamingRuntime = &FakeStreamingRuntime{}
  59. // FakeRuntime should implement Runtime.
  60. var _ Runtime = &FakeRuntime{}
  61. type FakeVersion struct {
  62. Version string
  63. }
  64. func (fv *FakeVersion) String() string {
  65. return fv.Version
  66. }
  67. func (fv *FakeVersion) Compare(other string) (int, error) {
  68. result := 0
  69. if fv.Version > other {
  70. result = 1
  71. } else if fv.Version < other {
  72. result = -1
  73. }
  74. return result, nil
  75. }
  76. type podsGetter interface {
  77. GetPods(bool) ([]*Pod, error)
  78. }
  79. type FakeRuntimeCache struct {
  80. getter podsGetter
  81. }
  82. func NewFakeRuntimeCache(getter podsGetter) RuntimeCache {
  83. return &FakeRuntimeCache{getter}
  84. }
  85. func (f *FakeRuntimeCache) GetPods() ([]*Pod, error) {
  86. return f.getter.GetPods(false)
  87. }
  88. func (f *FakeRuntimeCache) ForceUpdateIfOlder(time.Time) error {
  89. return nil
  90. }
  91. // ClearCalls resets the FakeRuntime to the initial state.
  92. func (f *FakeRuntime) ClearCalls() {
  93. f.Lock()
  94. defer f.Unlock()
  95. f.CalledFunctions = []string{}
  96. f.PodList = []*FakePod{}
  97. f.AllPodList = []*FakePod{}
  98. f.APIPodStatus = v1.PodStatus{}
  99. f.StartedPods = []string{}
  100. f.KilledPods = []string{}
  101. f.StartedContainers = []string{}
  102. f.KilledContainers = []string{}
  103. f.RuntimeStatus = nil
  104. f.VersionInfo = ""
  105. f.RuntimeType = ""
  106. f.Err = nil
  107. f.InspectErr = nil
  108. f.StatusErr = nil
  109. }
  110. // UpdatePodCIDR fulfills the cri interface.
  111. func (f *FakeRuntime) UpdatePodCIDR(c string) error {
  112. return nil
  113. }
  114. func (f *FakeRuntime) assertList(expect []string, test []string) error {
  115. if !reflect.DeepEqual(expect, test) {
  116. return fmt.Errorf("expected %#v, got %#v", expect, test)
  117. }
  118. return nil
  119. }
  120. // AssertCalls test if the invoked functions are as expected.
  121. func (f *FakeRuntime) AssertCalls(calls []string) error {
  122. f.Lock()
  123. defer f.Unlock()
  124. return f.assertList(calls, f.CalledFunctions)
  125. }
  126. func (f *FakeRuntime) AssertStartedPods(pods []string) error {
  127. f.Lock()
  128. defer f.Unlock()
  129. return f.assertList(pods, f.StartedPods)
  130. }
  131. func (f *FakeRuntime) AssertKilledPods(pods []string) error {
  132. f.Lock()
  133. defer f.Unlock()
  134. return f.assertList(pods, f.KilledPods)
  135. }
  136. func (f *FakeRuntime) AssertStartedContainers(containers []string) error {
  137. f.Lock()
  138. defer f.Unlock()
  139. return f.assertList(containers, f.StartedContainers)
  140. }
  141. func (f *FakeRuntime) AssertKilledContainers(containers []string) error {
  142. f.Lock()
  143. defer f.Unlock()
  144. return f.assertList(containers, f.KilledContainers)
  145. }
  146. func (f *FakeRuntime) Type() string {
  147. return f.RuntimeType
  148. }
  149. func (f *FakeRuntime) Version() (Version, error) {
  150. f.Lock()
  151. defer f.Unlock()
  152. f.CalledFunctions = append(f.CalledFunctions, "Version")
  153. return &FakeVersion{Version: f.VersionInfo}, f.Err
  154. }
  155. func (f *FakeRuntime) APIVersion() (Version, error) {
  156. f.Lock()
  157. defer f.Unlock()
  158. f.CalledFunctions = append(f.CalledFunctions, "APIVersion")
  159. return &FakeVersion{Version: f.APIVersionInfo}, f.Err
  160. }
  161. func (f *FakeRuntime) Status() (*RuntimeStatus, error) {
  162. f.Lock()
  163. defer f.Unlock()
  164. f.CalledFunctions = append(f.CalledFunctions, "Status")
  165. return f.RuntimeStatus, f.StatusErr
  166. }
  167. func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) {
  168. f.Lock()
  169. defer f.Unlock()
  170. var pods []*Pod
  171. f.CalledFunctions = append(f.CalledFunctions, "GetPods")
  172. if all {
  173. for _, fakePod := range f.AllPodList {
  174. pods = append(pods, fakePod.Pod)
  175. }
  176. } else {
  177. for _, fakePod := range f.PodList {
  178. pods = append(pods, fakePod.Pod)
  179. }
  180. }
  181. return pods, f.Err
  182. }
  183. func (f *FakeRuntime) SyncPod(pod *v1.Pod, _ *PodStatus, _ []v1.Secret, backOff *flowcontrol.Backoff) (result PodSyncResult) {
  184. f.Lock()
  185. defer f.Unlock()
  186. f.CalledFunctions = append(f.CalledFunctions, "SyncPod")
  187. f.StartedPods = append(f.StartedPods, string(pod.UID))
  188. for _, c := range pod.Spec.Containers {
  189. f.StartedContainers = append(f.StartedContainers, c.Name)
  190. }
  191. // TODO(random-liu): Add SyncResult for starting and killing containers
  192. if f.Err != nil {
  193. result.Fail(f.Err)
  194. }
  195. return
  196. }
  197. func (f *FakeRuntime) KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error {
  198. f.Lock()
  199. defer f.Unlock()
  200. f.CalledFunctions = append(f.CalledFunctions, "KillPod")
  201. f.KilledPods = append(f.KilledPods, string(runningPod.ID))
  202. for _, c := range runningPod.Containers {
  203. f.KilledContainers = append(f.KilledContainers, c.Name)
  204. }
  205. return f.Err
  206. }
  207. func (f *FakeRuntime) RunContainerInPod(container v1.Container, pod *v1.Pod, volumeMap map[string]volume.VolumePlugin) error {
  208. f.Lock()
  209. defer f.Unlock()
  210. f.CalledFunctions = append(f.CalledFunctions, "RunContainerInPod")
  211. f.StartedContainers = append(f.StartedContainers, container.Name)
  212. pod.Spec.Containers = append(pod.Spec.Containers, container)
  213. for _, c := range pod.Spec.Containers {
  214. if c.Name == container.Name { // Container already in the pod.
  215. return f.Err
  216. }
  217. }
  218. pod.Spec.Containers = append(pod.Spec.Containers, container)
  219. return f.Err
  220. }
  221. func (f *FakeRuntime) KillContainerInPod(container v1.Container, pod *v1.Pod) error {
  222. f.Lock()
  223. defer f.Unlock()
  224. f.CalledFunctions = append(f.CalledFunctions, "KillContainerInPod")
  225. f.KilledContainers = append(f.KilledContainers, container.Name)
  226. var containers []v1.Container
  227. for _, c := range pod.Spec.Containers {
  228. if c.Name == container.Name {
  229. continue
  230. }
  231. containers = append(containers, c)
  232. }
  233. return f.Err
  234. }
  235. func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error) {
  236. f.Lock()
  237. defer f.Unlock()
  238. f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
  239. status := f.PodStatus
  240. return &status, f.Err
  241. }
  242. func (f *FakeRuntime) GetContainerLogs(_ context.Context, pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) {
  243. f.Lock()
  244. defer f.Unlock()
  245. f.CalledFunctions = append(f.CalledFunctions, "GetContainerLogs")
  246. return f.Err
  247. }
  248. func (f *FakeRuntime) PullImage(image ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) {
  249. f.Lock()
  250. defer f.Unlock()
  251. f.CalledFunctions = append(f.CalledFunctions, "PullImage")
  252. return image.Image, f.Err
  253. }
  254. func (f *FakeRuntime) GetImageRef(image ImageSpec) (string, error) {
  255. f.Lock()
  256. defer f.Unlock()
  257. f.CalledFunctions = append(f.CalledFunctions, "GetImageRef")
  258. for _, i := range f.ImageList {
  259. if i.ID == image.Image {
  260. return i.ID, nil
  261. }
  262. }
  263. return "", f.InspectErr
  264. }
  265. func (f *FakeRuntime) ListImages() ([]Image, error) {
  266. f.Lock()
  267. defer f.Unlock()
  268. f.CalledFunctions = append(f.CalledFunctions, "ListImages")
  269. return f.ImageList, f.Err
  270. }
  271. func (f *FakeRuntime) RemoveImage(image ImageSpec) error {
  272. f.Lock()
  273. defer f.Unlock()
  274. f.CalledFunctions = append(f.CalledFunctions, "RemoveImage")
  275. index := 0
  276. for i := range f.ImageList {
  277. if f.ImageList[i].ID == image.Image {
  278. index = i
  279. break
  280. }
  281. }
  282. f.ImageList = append(f.ImageList[:index], f.ImageList[index+1:]...)
  283. return f.Err
  284. }
  285. func (f *FakeRuntime) GarbageCollect(gcPolicy ContainerGCPolicy, ready bool, evictNonDeletedPods bool) error {
  286. f.Lock()
  287. defer f.Unlock()
  288. f.CalledFunctions = append(f.CalledFunctions, "GarbageCollect")
  289. return f.Err
  290. }
  291. func (f *FakeRuntime) DeleteContainer(containerID ContainerID) error {
  292. f.Lock()
  293. defer f.Unlock()
  294. f.CalledFunctions = append(f.CalledFunctions, "DeleteContainer")
  295. return f.Err
  296. }
  297. func (f *FakeRuntime) ImageStats() (*ImageStats, error) {
  298. f.Lock()
  299. defer f.Unlock()
  300. f.CalledFunctions = append(f.CalledFunctions, "ImageStats")
  301. return nil, f.Err
  302. }
  303. func (f *FakeStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) {
  304. f.Lock()
  305. defer f.Unlock()
  306. f.CalledFunctions = append(f.CalledFunctions, "GetExec")
  307. return &url.URL{Host: FakeHost}, f.Err
  308. }
  309. func (f *FakeStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) {
  310. f.Lock()
  311. defer f.Unlock()
  312. f.CalledFunctions = append(f.CalledFunctions, "GetAttach")
  313. return &url.URL{Host: FakeHost}, f.Err
  314. }
  315. func (f *FakeStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) {
  316. f.Lock()
  317. defer f.Unlock()
  318. f.CalledFunctions = append(f.CalledFunctions, "GetPortForward")
  319. return &url.URL{Host: FakeHost}, f.Err
  320. }
  321. type FakeContainerCommandRunner struct {
  322. // what to return
  323. Stdout string
  324. Err error
  325. // actual values when invoked
  326. ContainerID ContainerID
  327. Cmd []string
  328. }
  329. var _ ContainerCommandRunner = &FakeContainerCommandRunner{}
  330. func (f *FakeContainerCommandRunner) RunInContainer(containerID ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
  331. // record invoked values
  332. f.ContainerID = containerID
  333. f.Cmd = cmd
  334. return []byte(f.Stdout), f.Err
  335. }