fake_runtime.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  27. "k8s.io/kubernetes/pkg/volume"
  28. )
  29. type FakePod struct {
  30. Pod *kubecontainer.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 []kubecontainer.Image
  40. APIPodStatus v1.PodStatus
  41. PodStatus kubecontainer.PodStatus
  42. StartedPods []string
  43. KilledPods []string
  44. StartedContainers []string
  45. KilledContainers []string
  46. RuntimeStatus *kubecontainer.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 _ kubecontainer.StreamingRuntime = &FakeStreamingRuntime{}
  59. // FakeRuntime should implement Runtime.
  60. var _ kubecontainer.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) ([]*kubecontainer.Pod, error)
  78. }
  79. type FakeRuntimeCache struct {
  80. getter podsGetter
  81. }
  82. func NewFakeRuntimeCache(getter podsGetter) kubecontainer.RuntimeCache {
  83. return &FakeRuntimeCache{getter}
  84. }
  85. func (f *FakeRuntimeCache) GetPods() ([]*kubecontainer.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) SupportsSingleFileMapping() bool {
  150. return true
  151. }
  152. func (f *FakeRuntime) Version() (kubecontainer.Version, error) {
  153. f.Lock()
  154. defer f.Unlock()
  155. f.CalledFunctions = append(f.CalledFunctions, "Version")
  156. return &FakeVersion{Version: f.VersionInfo}, f.Err
  157. }
  158. func (f *FakeRuntime) APIVersion() (kubecontainer.Version, error) {
  159. f.Lock()
  160. defer f.Unlock()
  161. f.CalledFunctions = append(f.CalledFunctions, "APIVersion")
  162. return &FakeVersion{Version: f.APIVersionInfo}, f.Err
  163. }
  164. func (f *FakeRuntime) Status() (*kubecontainer.RuntimeStatus, error) {
  165. f.Lock()
  166. defer f.Unlock()
  167. f.CalledFunctions = append(f.CalledFunctions, "Status")
  168. return f.RuntimeStatus, f.StatusErr
  169. }
  170. func (f *FakeRuntime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
  171. f.Lock()
  172. defer f.Unlock()
  173. var pods []*kubecontainer.Pod
  174. f.CalledFunctions = append(f.CalledFunctions, "GetPods")
  175. if all {
  176. for _, fakePod := range f.AllPodList {
  177. pods = append(pods, fakePod.Pod)
  178. }
  179. } else {
  180. for _, fakePod := range f.PodList {
  181. pods = append(pods, fakePod.Pod)
  182. }
  183. }
  184. return pods, f.Err
  185. }
  186. func (f *FakeRuntime) SyncPod(pod *v1.Pod, _ *kubecontainer.PodStatus, _ []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {
  187. f.Lock()
  188. defer f.Unlock()
  189. f.CalledFunctions = append(f.CalledFunctions, "SyncPod")
  190. f.StartedPods = append(f.StartedPods, string(pod.UID))
  191. for _, c := range pod.Spec.Containers {
  192. f.StartedContainers = append(f.StartedContainers, c.Name)
  193. }
  194. // TODO(random-liu): Add SyncResult for starting and killing containers
  195. if f.Err != nil {
  196. result.Fail(f.Err)
  197. }
  198. return
  199. }
  200. func (f *FakeRuntime) KillPod(pod *v1.Pod, runningPod kubecontainer.Pod, gracePeriodOverride *int64) error {
  201. f.Lock()
  202. defer f.Unlock()
  203. f.CalledFunctions = append(f.CalledFunctions, "KillPod")
  204. f.KilledPods = append(f.KilledPods, string(runningPod.ID))
  205. for _, c := range runningPod.Containers {
  206. f.KilledContainers = append(f.KilledContainers, c.Name)
  207. }
  208. return f.Err
  209. }
  210. func (f *FakeRuntime) RunContainerInPod(container v1.Container, pod *v1.Pod, volumeMap map[string]volume.VolumePlugin) error {
  211. f.Lock()
  212. defer f.Unlock()
  213. f.CalledFunctions = append(f.CalledFunctions, "RunContainerInPod")
  214. f.StartedContainers = append(f.StartedContainers, container.Name)
  215. pod.Spec.Containers = append(pod.Spec.Containers, container)
  216. for _, c := range pod.Spec.Containers {
  217. if c.Name == container.Name { // Container already in the pod.
  218. return f.Err
  219. }
  220. }
  221. pod.Spec.Containers = append(pod.Spec.Containers, container)
  222. return f.Err
  223. }
  224. func (f *FakeRuntime) KillContainerInPod(container v1.Container, pod *v1.Pod) error {
  225. f.Lock()
  226. defer f.Unlock()
  227. f.CalledFunctions = append(f.CalledFunctions, "KillContainerInPod")
  228. f.KilledContainers = append(f.KilledContainers, container.Name)
  229. return f.Err
  230. }
  231. func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*kubecontainer.PodStatus, error) {
  232. f.Lock()
  233. defer f.Unlock()
  234. f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
  235. status := f.PodStatus
  236. return &status, f.Err
  237. }
  238. func (f *FakeRuntime) GetContainerLogs(_ context.Context, pod *v1.Pod, containerID kubecontainer.ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) {
  239. f.Lock()
  240. defer f.Unlock()
  241. f.CalledFunctions = append(f.CalledFunctions, "GetContainerLogs")
  242. return f.Err
  243. }
  244. func (f *FakeRuntime) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) {
  245. f.Lock()
  246. defer f.Unlock()
  247. f.CalledFunctions = append(f.CalledFunctions, "PullImage")
  248. return image.Image, f.Err
  249. }
  250. func (f *FakeRuntime) GetImageRef(image kubecontainer.ImageSpec) (string, error) {
  251. f.Lock()
  252. defer f.Unlock()
  253. f.CalledFunctions = append(f.CalledFunctions, "GetImageRef")
  254. for _, i := range f.ImageList {
  255. if i.ID == image.Image {
  256. return i.ID, nil
  257. }
  258. }
  259. return "", f.InspectErr
  260. }
  261. func (f *FakeRuntime) ListImages() ([]kubecontainer.Image, error) {
  262. f.Lock()
  263. defer f.Unlock()
  264. f.CalledFunctions = append(f.CalledFunctions, "ListImages")
  265. return f.ImageList, f.Err
  266. }
  267. func (f *FakeRuntime) RemoveImage(image kubecontainer.ImageSpec) error {
  268. f.Lock()
  269. defer f.Unlock()
  270. f.CalledFunctions = append(f.CalledFunctions, "RemoveImage")
  271. index := 0
  272. for i := range f.ImageList {
  273. if f.ImageList[i].ID == image.Image {
  274. index = i
  275. break
  276. }
  277. }
  278. f.ImageList = append(f.ImageList[:index], f.ImageList[index+1:]...)
  279. return f.Err
  280. }
  281. func (f *FakeRuntime) GarbageCollect(gcPolicy kubecontainer.ContainerGCPolicy, ready bool, evictNonDeletedPods bool) error {
  282. f.Lock()
  283. defer f.Unlock()
  284. f.CalledFunctions = append(f.CalledFunctions, "GarbageCollect")
  285. return f.Err
  286. }
  287. func (f *FakeRuntime) DeleteContainer(containerID kubecontainer.ContainerID) error {
  288. f.Lock()
  289. defer f.Unlock()
  290. f.CalledFunctions = append(f.CalledFunctions, "DeleteContainer")
  291. return f.Err
  292. }
  293. func (f *FakeRuntime) ImageStats() (*kubecontainer.ImageStats, error) {
  294. f.Lock()
  295. defer f.Unlock()
  296. f.CalledFunctions = append(f.CalledFunctions, "ImageStats")
  297. return nil, f.Err
  298. }
  299. func (f *FakeStreamingRuntime) GetExec(id kubecontainer.ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) {
  300. f.Lock()
  301. defer f.Unlock()
  302. f.CalledFunctions = append(f.CalledFunctions, "GetExec")
  303. return &url.URL{Host: FakeHost}, f.Err
  304. }
  305. func (f *FakeStreamingRuntime) GetAttach(id kubecontainer.ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) {
  306. f.Lock()
  307. defer f.Unlock()
  308. f.CalledFunctions = append(f.CalledFunctions, "GetAttach")
  309. return &url.URL{Host: FakeHost}, f.Err
  310. }
  311. func (f *FakeStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) {
  312. f.Lock()
  313. defer f.Unlock()
  314. f.CalledFunctions = append(f.CalledFunctions, "GetPortForward")
  315. return &url.URL{Host: FakeHost}, f.Err
  316. }
  317. type FakeContainerCommandRunner struct {
  318. // what to return
  319. Stdout string
  320. Err error
  321. // actual values when invoked
  322. ContainerID kubecontainer.ContainerID
  323. Cmd []string
  324. }
  325. var _ kubecontainer.ContainerCommandRunner = &FakeContainerCommandRunner{}
  326. func (f *FakeContainerCommandRunner) RunInContainer(containerID kubecontainer.ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
  327. // record invoked values
  328. f.ContainerID = containerID
  329. f.Cmd = cmd
  330. return []byte(f.Stdout), f.Err
  331. }