mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 13:55:41 +00:00
Kubelet: implement fake runtime/image service
This commit is contained in:
parent
d9ca9e8cbf
commit
bf7a941b92
@ -18,30 +18,104 @@ package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
internalApi "k8s.io/kubernetes/pkg/kubelet/api"
|
||||
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/sliceutils"
|
||||
)
|
||||
|
||||
type fakeImageService struct {
|
||||
var (
|
||||
fakeImageSize uint64 = 1
|
||||
)
|
||||
|
||||
type FakeImageService struct {
|
||||
sync.Mutex
|
||||
|
||||
Called []string
|
||||
Images map[string]*runtimeApi.Image
|
||||
}
|
||||
|
||||
func NewFakeImageService() internalApi.ImageManagerService {
|
||||
return &fakeImageService{}
|
||||
func (r *FakeImageService) SetFakeImages(images []string) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Images = make(map[string]*runtimeApi.Image)
|
||||
for _, image := range images {
|
||||
r.Images[image] = makeFakeImage(image)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeImageService) ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func NewFakeImageService() *FakeImageService {
|
||||
return &FakeImageService{
|
||||
Called: make([]string, 0),
|
||||
Images: make(map[string]*runtimeApi.Image),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeImageService) ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func makeFakeImage(image string) *runtimeApi.Image {
|
||||
return &runtimeApi.Image{
|
||||
Id: &image,
|
||||
Size_: &fakeImageSize,
|
||||
RepoTags: []string{image},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeImageService) PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeImageService) ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "ListImages")
|
||||
|
||||
images := make([]*runtimeApi.Image, 0)
|
||||
for _, img := range r.Images {
|
||||
if filter != nil && filter.Image != nil {
|
||||
if !sliceutils.StringInSlice(filter.Image.GetImage(), img.RepoTags) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
images = append(images, img)
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
func (r *fakeImageService) RemoveImage(image *runtimeApi.ImageSpec) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeImageService) ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "ImageStatus")
|
||||
|
||||
if img, ok := r.Images[image.GetImage()]; ok {
|
||||
return img, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("image %q not found", image.GetImage())
|
||||
}
|
||||
|
||||
func (r *FakeImageService) PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "PullImage")
|
||||
|
||||
// ImageID should be randomized for real container runtime, but here just use
|
||||
// image's name for easily making fake images.
|
||||
imageID := image.GetImage()
|
||||
if _, ok := r.Images[imageID]; !ok {
|
||||
r.Images[imageID] = makeFakeImage(image.GetImage())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *FakeImageService) RemoveImage(image *runtimeApi.ImageSpec) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "RemoveImage")
|
||||
|
||||
// Remove the image
|
||||
delete(r.Images, image.GetImage())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -19,66 +19,354 @@ package testing
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
internalApi "k8s.io/kubernetes/pkg/kubelet/api"
|
||||
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||
)
|
||||
|
||||
type fakeRuntimeService struct {
|
||||
var (
|
||||
version = "0.1.0"
|
||||
|
||||
fakeRuntimeName = "fakeRuntime"
|
||||
fakePodSandboxIP = "192.168.192.168"
|
||||
)
|
||||
|
||||
type FakePodSandbox struct {
|
||||
// PodSandbox contains minimal information about a sandbox.
|
||||
runtimeApi.PodSandbox
|
||||
|
||||
// Annotations is an unstructured key value map that may be set by external
|
||||
// tools to store and retrieve arbitrary metadata.
|
||||
Annotations map[string]string
|
||||
}
|
||||
|
||||
func NewFakeRuntimeService() internalApi.RuntimeService {
|
||||
return &fakeRuntimeService{}
|
||||
type FakeContainer struct {
|
||||
// ContainerStatus contains the runtime information for a container.
|
||||
runtimeApi.ContainerStatus
|
||||
|
||||
// the sandbox id of this container
|
||||
SandboxID string
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) Version(apiVersion string) (*runtimeApi.VersionResponse, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
type FakeRuntimeService struct {
|
||||
sync.Mutex
|
||||
|
||||
Called []string
|
||||
|
||||
Containers map[string]*FakeContainer
|
||||
Sandboxes map[string]*FakePodSandbox
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) {
|
||||
return "", fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) SetFakeSandboxes(sandboxes []*FakePodSandbox) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Sandboxes = make(map[string]*FakePodSandbox)
|
||||
for _, sandbox := range sandboxes {
|
||||
sandboxID := sandbox.GetId()
|
||||
r.Sandboxes[sandboxID] = sandbox
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) StopPodSandbox(podSandboxID string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) SetFakeContainers(containers []*FakeContainer) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Containers = make(map[string]*FakeContainer)
|
||||
for _, c := range containers {
|
||||
containerID := c.GetName()
|
||||
r.Containers[containerID] = c
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) DeletePodSandbox(podSandboxID string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func NewFakeRuntimeService() *FakeRuntimeService {
|
||||
return &FakeRuntimeService{
|
||||
Called: make([]string, 0),
|
||||
Containers: make(map[string]*FakeContainer),
|
||||
Sandboxes: make(map[string]*FakePodSandbox),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) Version(apiVersion string) (*runtimeApi.VersionResponse, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "Version")
|
||||
|
||||
return &runtimeApi.VersionResponse{
|
||||
Version: &version,
|
||||
RuntimeName: &fakeRuntimeName,
|
||||
RuntimeVersion: &version,
|
||||
RuntimeApiVersion: &version,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "CreatePodSandbox")
|
||||
|
||||
// PodSandboxID should be randomized for real container runtime, but here just use
|
||||
// sandbox's name for easily making fake sandboxes.
|
||||
podSandboxID := config.GetName()
|
||||
createdAt := time.Now().Unix()
|
||||
readyState := runtimeApi.PodSandBoxState_READY
|
||||
r.Sandboxes[podSandboxID] = &FakePodSandbox{
|
||||
PodSandbox: runtimeApi.PodSandbox{
|
||||
Id: &podSandboxID,
|
||||
Name: config.Name,
|
||||
State: &readyState,
|
||||
CreatedAt: &createdAt,
|
||||
Labels: config.Labels,
|
||||
},
|
||||
Annotations: config.Annotations,
|
||||
}
|
||||
|
||||
return podSandboxID, nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) {
|
||||
return "", fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) StopPodSandbox(podSandboxID string) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "StopPodSandbox")
|
||||
|
||||
notReadyState := runtimeApi.PodSandBoxState_NOTREADY
|
||||
if s, ok := r.Sandboxes[podSandboxID]; ok {
|
||||
s.State = ¬ReadyState
|
||||
} else {
|
||||
return fmt.Errorf("pod sandbox %s not found", podSandboxID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) StartContainer(rawContainerID string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) DeletePodSandbox(podSandboxID string) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "DeletePodSandbox")
|
||||
|
||||
// Remove the pod sandbox
|
||||
delete(r.Sandboxes, podSandboxID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) StopContainer(rawContainerID string, timeout int64) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "PodSandboxStatus")
|
||||
|
||||
s, ok := r.Sandboxes[podSandboxID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("pod sandbox %q not found", podSandboxID)
|
||||
}
|
||||
|
||||
return &runtimeApi.PodSandboxStatus{
|
||||
Id: &podSandboxID,
|
||||
Name: s.Name,
|
||||
CreatedAt: s.CreatedAt,
|
||||
State: s.State,
|
||||
Network: &runtimeApi.PodSandboxNetworkStatus{
|
||||
Ip: &fakePodSandboxIP,
|
||||
},
|
||||
Labels: s.Labels,
|
||||
Annotations: s.Annotations,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) RemoveContainer(rawContainerID string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "ListPodSandbox")
|
||||
|
||||
result := make([]*runtimeApi.PodSandbox, 0)
|
||||
for id, s := range r.Sandboxes {
|
||||
if filter != nil {
|
||||
if filter.Id != nil && filter.GetId() != id {
|
||||
continue
|
||||
}
|
||||
if filter.Name != nil && filter.GetName() != s.GetName() {
|
||||
continue
|
||||
}
|
||||
if filter.State != nil && filter.GetState() != s.GetState() {
|
||||
continue
|
||||
}
|
||||
if filter.LabelSelector != nil && !filterInLabels(filter.LabelSelector, s.GetLabels()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, &runtimeApi.PodSandbox{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
State: s.State,
|
||||
CreatedAt: s.CreatedAt,
|
||||
Labels: s.Labels,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "CreateContainer")
|
||||
|
||||
// ContainerID should be randomized for real container runtime, but here just use
|
||||
// container's name for easily making fake containers.
|
||||
containerID := config.GetName()
|
||||
createdAt := time.Now().Unix()
|
||||
createdState := runtimeApi.ContainerState_CREATED
|
||||
imageRef := config.Image.GetImage()
|
||||
r.Containers[containerID] = &FakeContainer{
|
||||
ContainerStatus: runtimeApi.ContainerStatus{
|
||||
Id: &containerID,
|
||||
Name: config.Name,
|
||||
Image: config.Image,
|
||||
ImageRef: &imageRef,
|
||||
CreatedAt: &createdAt,
|
||||
State: &createdState,
|
||||
Labels: config.Labels,
|
||||
Annotations: config.Annotations,
|
||||
},
|
||||
SandboxID: podSandboxID,
|
||||
}
|
||||
|
||||
return containerID, nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) StartContainer(rawContainerID string) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "StartContainer")
|
||||
|
||||
c, ok := r.Containers[rawContainerID]
|
||||
if !ok {
|
||||
return fmt.Errorf("container %s not found", rawContainerID)
|
||||
}
|
||||
|
||||
// Set container to running.
|
||||
startedAt := time.Now().Unix()
|
||||
runningState := runtimeApi.ContainerState_RUNNING
|
||||
c.State = &runningState
|
||||
c.StartedAt = &startedAt
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fakeRuntimeService) Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
func (r *FakeRuntimeService) StopContainer(rawContainerID string, timeout int64) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "StopContainer")
|
||||
|
||||
c, ok := r.Containers[rawContainerID]
|
||||
if !ok {
|
||||
return fmt.Errorf("container %q not found", rawContainerID)
|
||||
}
|
||||
|
||||
// Set container to exited state.
|
||||
finishedAt := time.Now().Unix()
|
||||
exitedState := runtimeApi.ContainerState_EXITED
|
||||
c.State = &exitedState
|
||||
c.FinishedAt = &finishedAt
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *FakeRuntimeService) RemoveContainer(rawContainerID string) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "RemoveContainer")
|
||||
|
||||
// Remove the container
|
||||
delete(r.Containers, rawContainerID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *FakeRuntimeService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "ListContainers")
|
||||
|
||||
result := make([]*runtimeApi.Container, 0)
|
||||
for _, s := range r.Containers {
|
||||
if filter != nil {
|
||||
if filter.Id != nil && filter.GetId() != s.GetId() {
|
||||
continue
|
||||
}
|
||||
if filter.Name != nil && filter.GetName() != s.GetName() {
|
||||
continue
|
||||
}
|
||||
if filter.PodSandboxId != nil && filter.GetPodSandboxId() != s.SandboxID {
|
||||
continue
|
||||
}
|
||||
if filter.State != nil && filter.GetState() != s.GetState() {
|
||||
continue
|
||||
}
|
||||
if filter.LabelSelector != nil && !filterInLabels(filter.LabelSelector, s.GetLabels()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, &runtimeApi.Container{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
State: s.State,
|
||||
Image: s.Image,
|
||||
ImageRef: s.ImageRef,
|
||||
Labels: s.Labels,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *FakeRuntimeService) ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "ContainerStatus")
|
||||
|
||||
c, ok := r.Containers[rawContainerID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("container %q not found", rawContainerID)
|
||||
}
|
||||
|
||||
return &runtimeApi.ContainerStatus{
|
||||
Id: c.Id,
|
||||
Name: c.Name,
|
||||
State: c.State,
|
||||
CreatedAt: c.CreatedAt,
|
||||
Image: c.Image,
|
||||
ImageRef: c.ImageRef,
|
||||
Labels: c.Labels,
|
||||
Annotations: c.Annotations,
|
||||
ExitCode: c.ExitCode,
|
||||
StartedAt: c.StartedAt,
|
||||
FinishedAt: c.FinishedAt,
|
||||
Reason: c.Reason,
|
||||
Mounts: c.Mounts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *FakeRuntimeService) Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Called = append(r.Called, "Exec")
|
||||
return nil
|
||||
}
|
||||
|
31
pkg/kubelet/api/testing/utils.go
Normal file
31
pkg/kubelet/api/testing/utils.go
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright 2016 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
|
||||
|
||||
func filterInLabels(filter, labels map[string]string) bool {
|
||||
for k, v := range filter {
|
||||
if value, ok := labels[k]; ok {
|
||||
if value != v {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
27
pkg/kubelet/util/sliceutils/sliceutils.go
Normal file
27
pkg/kubelet/util/sliceutils/sliceutils.go
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
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 sliceutils
|
||||
|
||||
func StringInSlice(s string, list []string) bool {
|
||||
for _, v := range list {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user