123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- /*
- Copyright 2015 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package testing
- import (
- "context"
- "fmt"
- "io"
- "net/url"
- "reflect"
- "sync"
- "time"
- "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/types"
- "k8s.io/client-go/util/flowcontrol"
- runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
- kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
- "k8s.io/kubernetes/pkg/volume"
- )
- type FakePod struct {
- Pod *kubecontainer.Pod
- NetnsPath string
- }
- // FakeRuntime is a fake container runtime for testing.
- type FakeRuntime struct {
- sync.Mutex
- CalledFunctions []string
- PodList []*FakePod
- AllPodList []*FakePod
- ImageList []kubecontainer.Image
- APIPodStatus v1.PodStatus
- PodStatus kubecontainer.PodStatus
- StartedPods []string
- KilledPods []string
- StartedContainers []string
- KilledContainers []string
- RuntimeStatus *kubecontainer.RuntimeStatus
- VersionInfo string
- APIVersionInfo string
- RuntimeType string
- Err error
- InspectErr error
- StatusErr error
- }
- const FakeHost = "localhost:12345"
- type FakeStreamingRuntime struct {
- *FakeRuntime
- }
- var _ kubecontainer.StreamingRuntime = &FakeStreamingRuntime{}
- // FakeRuntime should implement Runtime.
- var _ kubecontainer.Runtime = &FakeRuntime{}
- type FakeVersion struct {
- Version string
- }
- func (fv *FakeVersion) String() string {
- return fv.Version
- }
- func (fv *FakeVersion) Compare(other string) (int, error) {
- result := 0
- if fv.Version > other {
- result = 1
- } else if fv.Version < other {
- result = -1
- }
- return result, nil
- }
- type podsGetter interface {
- GetPods(bool) ([]*kubecontainer.Pod, error)
- }
- type FakeRuntimeCache struct {
- getter podsGetter
- }
- func NewFakeRuntimeCache(getter podsGetter) kubecontainer.RuntimeCache {
- return &FakeRuntimeCache{getter}
- }
- func (f *FakeRuntimeCache) GetPods() ([]*kubecontainer.Pod, error) {
- return f.getter.GetPods(false)
- }
- func (f *FakeRuntimeCache) ForceUpdateIfOlder(time.Time) error {
- return nil
- }
- // ClearCalls resets the FakeRuntime to the initial state.
- func (f *FakeRuntime) ClearCalls() {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = []string{}
- f.PodList = []*FakePod{}
- f.AllPodList = []*FakePod{}
- f.APIPodStatus = v1.PodStatus{}
- f.StartedPods = []string{}
- f.KilledPods = []string{}
- f.StartedContainers = []string{}
- f.KilledContainers = []string{}
- f.RuntimeStatus = nil
- f.VersionInfo = ""
- f.RuntimeType = ""
- f.Err = nil
- f.InspectErr = nil
- f.StatusErr = nil
- }
- // UpdatePodCIDR fulfills the cri interface.
- func (f *FakeRuntime) UpdatePodCIDR(c string) error {
- return nil
- }
- func (f *FakeRuntime) assertList(expect []string, test []string) error {
- if !reflect.DeepEqual(expect, test) {
- return fmt.Errorf("expected %#v, got %#v", expect, test)
- }
- return nil
- }
- // AssertCalls test if the invoked functions are as expected.
- func (f *FakeRuntime) AssertCalls(calls []string) error {
- f.Lock()
- defer f.Unlock()
- return f.assertList(calls, f.CalledFunctions)
- }
- func (f *FakeRuntime) AssertStartedPods(pods []string) error {
- f.Lock()
- defer f.Unlock()
- return f.assertList(pods, f.StartedPods)
- }
- func (f *FakeRuntime) AssertKilledPods(pods []string) error {
- f.Lock()
- defer f.Unlock()
- return f.assertList(pods, f.KilledPods)
- }
- func (f *FakeRuntime) AssertStartedContainers(containers []string) error {
- f.Lock()
- defer f.Unlock()
- return f.assertList(containers, f.StartedContainers)
- }
- func (f *FakeRuntime) AssertKilledContainers(containers []string) error {
- f.Lock()
- defer f.Unlock()
- return f.assertList(containers, f.KilledContainers)
- }
- func (f *FakeRuntime) Type() string {
- return f.RuntimeType
- }
- func (f *FakeRuntime) SupportsSingleFileMapping() bool {
- return true
- }
- func (f *FakeRuntime) Version() (kubecontainer.Version, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "Version")
- return &FakeVersion{Version: f.VersionInfo}, f.Err
- }
- func (f *FakeRuntime) APIVersion() (kubecontainer.Version, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "APIVersion")
- return &FakeVersion{Version: f.APIVersionInfo}, f.Err
- }
- func (f *FakeRuntime) Status() (*kubecontainer.RuntimeStatus, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "Status")
- return f.RuntimeStatus, f.StatusErr
- }
- func (f *FakeRuntime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
- f.Lock()
- defer f.Unlock()
- var pods []*kubecontainer.Pod
- f.CalledFunctions = append(f.CalledFunctions, "GetPods")
- if all {
- for _, fakePod := range f.AllPodList {
- pods = append(pods, fakePod.Pod)
- }
- } else {
- for _, fakePod := range f.PodList {
- pods = append(pods, fakePod.Pod)
- }
- }
- return pods, f.Err
- }
- func (f *FakeRuntime) SyncPod(pod *v1.Pod, _ *kubecontainer.PodStatus, _ []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "SyncPod")
- f.StartedPods = append(f.StartedPods, string(pod.UID))
- for _, c := range pod.Spec.Containers {
- f.StartedContainers = append(f.StartedContainers, c.Name)
- }
- // TODO(random-liu): Add SyncResult for starting and killing containers
- if f.Err != nil {
- result.Fail(f.Err)
- }
- return
- }
- func (f *FakeRuntime) KillPod(pod *v1.Pod, runningPod kubecontainer.Pod, gracePeriodOverride *int64) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "KillPod")
- f.KilledPods = append(f.KilledPods, string(runningPod.ID))
- for _, c := range runningPod.Containers {
- f.KilledContainers = append(f.KilledContainers, c.Name)
- }
- return f.Err
- }
- func (f *FakeRuntime) RunContainerInPod(container v1.Container, pod *v1.Pod, volumeMap map[string]volume.VolumePlugin) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "RunContainerInPod")
- f.StartedContainers = append(f.StartedContainers, container.Name)
- pod.Spec.Containers = append(pod.Spec.Containers, container)
- for _, c := range pod.Spec.Containers {
- if c.Name == container.Name { // Container already in the pod.
- return f.Err
- }
- }
- pod.Spec.Containers = append(pod.Spec.Containers, container)
- return f.Err
- }
- func (f *FakeRuntime) KillContainerInPod(container v1.Container, pod *v1.Pod) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "KillContainerInPod")
- f.KilledContainers = append(f.KilledContainers, container.Name)
- return f.Err
- }
- func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*kubecontainer.PodStatus, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
- status := f.PodStatus
- return &status, f.Err
- }
- func (f *FakeRuntime) GetContainerLogs(_ context.Context, pod *v1.Pod, containerID kubecontainer.ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetContainerLogs")
- return f.Err
- }
- func (f *FakeRuntime) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "PullImage")
- return image.Image, f.Err
- }
- func (f *FakeRuntime) GetImageRef(image kubecontainer.ImageSpec) (string, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetImageRef")
- for _, i := range f.ImageList {
- if i.ID == image.Image {
- return i.ID, nil
- }
- }
- return "", f.InspectErr
- }
- func (f *FakeRuntime) ListImages() ([]kubecontainer.Image, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "ListImages")
- return f.ImageList, f.Err
- }
- func (f *FakeRuntime) RemoveImage(image kubecontainer.ImageSpec) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "RemoveImage")
- index := 0
- for i := range f.ImageList {
- if f.ImageList[i].ID == image.Image {
- index = i
- break
- }
- }
- f.ImageList = append(f.ImageList[:index], f.ImageList[index+1:]...)
- return f.Err
- }
- func (f *FakeRuntime) GarbageCollect(gcPolicy kubecontainer.ContainerGCPolicy, ready bool, evictNonDeletedPods bool) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GarbageCollect")
- return f.Err
- }
- func (f *FakeRuntime) DeleteContainer(containerID kubecontainer.ContainerID) error {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "DeleteContainer")
- return f.Err
- }
- func (f *FakeRuntime) ImageStats() (*kubecontainer.ImageStats, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "ImageStats")
- return nil, f.Err
- }
- func (f *FakeStreamingRuntime) GetExec(id kubecontainer.ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetExec")
- return &url.URL{Host: FakeHost}, f.Err
- }
- func (f *FakeStreamingRuntime) GetAttach(id kubecontainer.ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetAttach")
- return &url.URL{Host: FakeHost}, f.Err
- }
- func (f *FakeStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) {
- f.Lock()
- defer f.Unlock()
- f.CalledFunctions = append(f.CalledFunctions, "GetPortForward")
- return &url.URL{Host: FakeHost}, f.Err
- }
- type FakeContainerCommandRunner struct {
- // what to return
- Stdout string
- Err error
- // actual values when invoked
- ContainerID kubecontainer.ContainerID
- Cmd []string
- }
- var _ kubecontainer.ContainerCommandRunner = &FakeContainerCommandRunner{}
- func (f *FakeContainerCommandRunner) RunInContainer(containerID kubecontainer.ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
- // record invoked values
- f.ContainerID = containerID
- f.Cmd = cmd
- return []byte(f.Stdout), f.Err
- }
|