summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKubeEdge Bot <48982446+kubeedge-bot@users.noreply.github.com>2022-03-04 16:22:43 +0800
committerGitHub <noreply@github.com>2022-03-04 16:22:43 +0800
commit5e63a9508950c8df28cb0fd9dafdd9ed22eb535e (patch)
tree3da50d2d065643d9968a0c503b12bf3165decb0a
parentMerge pull request #3534 from gy95/keadmconfig (diff)
parentupdate vendor (diff)
downloadkubeedge-1.10.0-beta.0.tar.gz
Merge pull request #3637 from wackxu/edgemarkv1.10.0-beta.0
Add Edgemark for scalability test
-rw-r--r--Makefile11
-rw-r--r--build/edgemark/Dockerfile19
-rw-r--r--build/edgemark/README.md48
-rw-r--r--build/edgemark/edgemark_setup_guide.md97
-rw-r--r--build/edgemark/hollow_edge_node_template.yaml50
-rw-r--r--build/edgemark/images/edgemark.jpgbin0 -> 53675 bytes
-rw-r--r--edge/cmd/edgemark/hollow_edgecore.go153
-rw-r--r--edge/pkg/edged/edged.go10
-rwxr-xr-xhack/lib/golang.sh1
-rwxr-xr-xhack/make-rules/crossbuildimage.sh3
-rwxr-xr-xhack/make-rules/image.sh1
-rw-r--r--vendor/k8s.io/cri-api/pkg/apis/testing/fake_image_service.go230
-rw-r--r--vendor/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go636
-rw-r--r--vendor/k8s.io/cri-api/pkg/apis/testing/utils.go48
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/doc.go19
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint.go34
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint_windows.go40
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_image_service.go81
-rw-r--r--vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_runtime.go303
-rw-r--r--vendor/modules.txt2
20 files changed, 1779 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 38d8654a8..5ffe8c3ea 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,8 @@ BINARIES=cloudcore \
edgesite-server \
keadm \
csidriver \
- iptablesmanager
+ iptablesmanager \
+ edgemark
COMPONENTS=cloud \
edge
@@ -46,7 +47,7 @@ ifeq ($(HELP),y)
all: clean
@echo "$$ALL_HELP_INFO"
else
-all:
+all:
KUBEEDGE_OUTPUT_SUBPATH=$(OUT_DIR) hack/make-rules/build.sh $(WHAT)
endif
@@ -174,7 +175,7 @@ ifeq ($(HELP),y)
crossbuild:
@echo "$$CROSSBUILD_HELP_INFO"
else
-crossbuild:
+crossbuild:
hack/make-rules/crossbuild.sh $(WHAT) $(ARM_VERSION)
endif
@@ -194,7 +195,7 @@ define GENERATE_CRDS_HELP_INFO
# RELIABLESYNCS_VERSION, default: v1alpha1
#
# Example:
-# make generate
+# make generate
# make generate -e CRD_VERSIONS=v1 -e CRD_OUTPUTS=build/crds
#
endef
@@ -227,7 +228,7 @@ ifeq ($(HELP),y)
smallbuild:
@echo "$$SMALLBUILD_HELP_INFO"
else
-smallbuild:
+smallbuild:
hack/make-rules/smallbuild.sh $(WHAT)
endif
diff --git a/build/edgemark/Dockerfile b/build/edgemark/Dockerfile
new file mode 100644
index 000000000..8f4b85884
--- /dev/null
+++ b/build/edgemark/Dockerfile
@@ -0,0 +1,19 @@
+ARG BUILD_FROM=golang:1.16-alpine3.13
+
+FROM ${BUILD_FROM} AS builder
+
+ARG GO_LDFLAGS
+
+COPY . /go/src/github.com/kubeedge/kubeedge
+
+RUN apk --no-cache update && \
+apk --no-cache upgrade && \
+apk --no-cache add build-base linux-headers sqlite-dev binutils-gold && \
+CGO_ENABLED=1 GO111MODULE=off go build -v -o /usr/local/bin/edgemark -ldflags="${GO_LDFLAGS} -w -s -extldflags -static" \
+github.com/kubeedge/kubeedge/edge/cmd/edgemark
+
+FROM alpine:3.13
+
+COPY --from=builder /usr/local/bin/edgemark /usr/local/bin/edgemark
+
+ENTRYPOINT ["edgemark"] \ No newline at end of file
diff --git a/build/edgemark/README.md b/build/edgemark/README.md
new file mode 100644
index 000000000..d74d5becf
--- /dev/null
+++ b/build/edgemark/README.md
@@ -0,0 +1,48 @@
+# Edgemark User Guide
+
+## Introduction
+
+Edgemark is a performance testing tool that inspired by
+[Kubemark](https://github.com/kubernetes/kubernetes/tree/master/cmd/kubemark)
+which allows users to run experiments on
+simulated clusters. The primary use case is scalability testing, as simulated
+clusters can be much bigger than the real ones. The objective is to expose
+problems with the KubeEdge cloud components CloudCore that appear only on bigger clusters.
+
+This document serves as a primer to understand what Edgemark is, what it is not,
+and how to use it.
+
+## Architecture
+
+On a very high level, Edgemark cluster consists of three parts: a real kubernetes master,
+KubeEdge CloudCore component and a set of “Hollow” Edge Nodes. Hollow Edge Node is registered
+with `HollowEdgeCore`, which pretends to be an ordinary EdgeCore, but does not create any real containers.
+`HollowEdgeCore` mocks runtime manager with Kubernetes `k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_runtime.go`,
+where most logic sits. Except for simulating runtime manager, other behaviors is the same as edgecore.
+
+![img](images/edgemark.jpg)
+
+Currently, Kubernetes master components run on a dedicated machine as pods that are
+created/managed by kubelet, which itself runs as either a systemd or a supervisord
+service on the master VM depending on the VM distro. Having a dedicated machine for the master
+has a slight advantage over running the master components on an external cluster,
+which is being able to completely isolate master resources from everything else.
+The CloudCore has multiple instances and requires multiple dedicated nodes to maintain high reliability.
+Usually In highly available configurations, a load balancer must sit in front of the CloudCore
+to correctly route requests to healthy CloudCore servers. And The HollowEdgeNodes
+on the other hand are run on an ‘external’ Kubernetes cluster
+as pods in an isolated namespace (named edgemark). This idea of using pods on a
+real cluster behave (or act) as nodes on the edgemark cluster lies at the heart of
+edgemark's design.
+
+## Requirements
+
+To run Edgemark, you need:
+
+1. A Kubernetes cluster (called `external cluster`) for running all your HollowEdgeNodes
+2. A Kubernetes cluster (called `edgemark cluster`) the master for HollowEdgeNodes.
+3. Several dedicated nodes in `edgemark cluster` for deploy CloudCore, a load balancer
+ that expose CloudCore service for HollowEdgeNodes and the load balancer has to be directly
+ routable from HollowEdgeNodes.
+4. You also need access to a Docker repository that has the
+ container images for CloudCore, hollow-edge-node and node-problem-detector.
diff --git a/build/edgemark/edgemark_setup_guide.md b/build/edgemark/edgemark_setup_guide.md
new file mode 100644
index 000000000..fd0a48885
--- /dev/null
+++ b/build/edgemark/edgemark_setup_guide.md
@@ -0,0 +1,97 @@
+## Introduction
+This document serves to understand how to set up edgemark cluster given
+that a base cluster (to run hollow-edge-node pods) and
+separate master (to act as master for the hollow edge nodes) are already present.
+
+## Precondition
+You need edgemark master and external cluster to set up a edgemark cluster.
+
+The functions are as follows:
+
+- edgemark master: can be StandAlone or HA, used to be the edgemark cluster's master
+- external cluster: used to create hollow edge nodes for the edgemark cluster
+
+## Steps:
+1. Deploy CloudCore in edgemark cluster, refer to [CloudCore deploy](https://kubeedge.io/en/docs/setup/ha/) for more details.
+
+2. Build edgemark image
+
+If you want to build/use your own edgemark image, do as follows.
+
+- i. pull kubeedge code
+
+```
+cd $GOPATH/src/github.com/kubeedge
+git clone git@github.com:kubeedge/kubeedge.git
+```
+
+- ii. build edgemark image
+
+```
+cd $GOPATH/src/github.com/kubeedge/kubeedge
+make image WHAT=edgemark
+```
+
+Then you can get the image named `kubeedge/edgemark:{tag}` locally.
+
+3. Create hollow nodes in external cluster
+
+- i. create namespace and secret
+
+Copy edgemark master's `tokensecret` which is generated by CloudCore which is used to access CloudCore for edge node,
+and create it in namespace that will deploy hollow edge node in external cluster.
+
+first, save `tokensecret` in file from edgemark cluster,
+
+```
+kubectl get secret -nkubeedge tokensecret -oyaml > tokensecret.yaml
+```
+
+modify namespace in `tokensecret.yaml`
+```
+sed -i "s|namespace: .*|namespace: {ns}|g" tokensecret.yaml
+```
+
+create ns and tokensecret in external cluster
+
+```
+kubectl create ns edgemark
+
+kubectl create -f tokensecret.yaml
+```
+
+- ii. apply yaml to create hollow nodes
+
+You can use `hollow-edge-node_template.yaml` in the current directory.
+
+Note:
+
+- the parameters `{{numreplicas}}` means the number of hollow nodes in the edgemark cluster
+- the parameters `{{server}}` means the server address exposed for hollow nodes join in
+- the parameters `{{server}}`, `{{numreplicas}}`, `{{edgemark_image_registry}}` and `{{edgemark_image_tag}}` need to be filled in the template
+- your external cluster should have enough resources to be able to run `{{numreplicas}}` no. of hollow-node pods
+
+```
+kubectl create -f hollow-edge-node_template.yaml
+```
+
+Waiting for these hollow-node pods to be running. Then you can see these pods register as edgemark master's nodes.
+
+Finally, edgemark master and external cluster set up the edgemark cluster.
+
+
+4. Run performance testing with ClusterLoader2
+
+After set up the edgemark cluster, we can do our performance testing with ClusterLoader2.
+[ClusterLoader2](https://github.com/kubernetes/perf-tests/tree/master/clusterloader2) is
+an official K8s scalability and performance testing framework.
+refer to [ClusterLoader2 Getting started](https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/docs/GETTING_STARTED.md) for more details.
+we just need config `--provider=kubemark` when we run performance test, for example:
+
+```
+./clusterloader --testconfig=config.yaml --provider=kubemark --kubeconfig=${HOME}/.kube/config --v=2
+```
+
+
+
+
diff --git a/build/edgemark/hollow_edge_node_template.yaml b/build/edgemark/hollow_edge_node_template.yaml
new file mode 100644
index 000000000..aa677ad94
--- /dev/null
+++ b/build/edgemark/hollow_edge_node_template.yaml
@@ -0,0 +1,50 @@
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+ name: hollow-edge-node
+spec:
+ replicas: {{numreplicas}}
+ selector:
+ matchLabels:
+ app: hollow-edge-node
+ template:
+ metadata:
+ labels:
+ app: hollow-edge-node
+ spec:
+ containers:
+ - name: hollow-edgecore
+ image: {{edgemark_image_registry}}/edgemark:{{edgemark_image_tag}}
+ command:
+ - edgemark
+ args:
+ - --token=$(TOKEN)
+ - --name=$(NODE_NAME)
+ - --http-server=https://{{server}}:10002
+ - --websocket-server={{server}}:10000
+ - --alsologtostderr
+ - --v=2
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ apiVersion: v1
+ fieldPath: metadata.name
+ - name: TOKEN
+ valueFrom:
+ secretKeyRef:
+ name: tokensecret
+ key: tokendata
+ resources:
+ requests:
+ cpu: 20m
+ memory: 50M
+ securityContext:
+ privileged: true
+ tolerations:
+ - effect: NoExecute
+ key: node.kubernetes.io/unreachable
+ operator: Exists
+ - effect: NoExecute
+ key: node.kubernetes.io/not-ready
+ operator: Exists
diff --git a/build/edgemark/images/edgemark.jpg b/build/edgemark/images/edgemark.jpg
new file mode 100644
index 000000000..2dfe3dadf
--- /dev/null
+++ b/build/edgemark/images/edgemark.jpg
Binary files differ
diff --git a/edge/cmd/edgemark/hollow_edgecore.go b/edge/cmd/edgemark/hollow_edgecore.go
new file mode 100644
index 000000000..c76ff63f8
--- /dev/null
+++ b/edge/cmd/edgemark/hollow_edgecore.go
@@ -0,0 +1,153 @@
+/*
+Copyright 2022 The KubeEdge 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 main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "time"
+
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ cliflag "k8s.io/component-base/cli/flag"
+ internalapi "k8s.io/cri-api/pkg/apis"
+ "k8s.io/kubernetes/pkg/kubelet/cri/remote"
+ fakeremote "k8s.io/kubernetes/pkg/kubelet/cri/remote/fake"
+
+ "github.com/kubeedge/beehive/pkg/core"
+ "github.com/kubeedge/kubeedge/edge/pkg/common/dbm"
+ "github.com/kubeedge/kubeedge/edge/pkg/edged"
+ "github.com/kubeedge/kubeedge/edge/pkg/edgehub"
+ "github.com/kubeedge/kubeedge/edge/pkg/metamanager"
+ "github.com/kubeedge/kubeedge/pkg/apis/componentconfig/edgecore/v1alpha1"
+ "github.com/kubeedge/kubeedge/pkg/version/verflag"
+)
+
+type hollowEdgeNodeConfig struct {
+ Token string
+ NodeName string
+ HTTPServer string
+ WebsocketServer string
+ NodeLabels map[string]string
+}
+
+func main() {
+ command := newHollowEdgeNodeCommand()
+ if err := command.Execute(); err != nil {
+ os.Exit(1)
+ }
+}
+
+// newHollowEdgeNodeCommand creates a *cobra.Command object with default parameters
+func newHollowEdgeNodeCommand() *cobra.Command {
+ s := &hollowEdgeNodeConfig{
+ NodeLabels: make(map[string]string),
+ }
+
+ cmd := &cobra.Command{
+ Use: "edgemark",
+ Long: "edgemark",
+ Run: func(cmd *cobra.Command, args []string) {
+ verflag.PrintAndExitIfRequested()
+ run(s)
+ },
+ Args: func(cmd *cobra.Command, args []string) error {
+ for _, arg := range args {
+ if len(arg) > 0 {
+ return fmt.Errorf("%q does not take any arguments, got %q", cmd.CommandPath(), args)
+ }
+ }
+ return nil
+ },
+ }
+
+ fs := cmd.Flags()
+ fs.AddGoFlagSet(flag.CommandLine) // for flags like --docker-only
+ s.addFlags(fs)
+
+ return cmd
+}
+
+func run(config *hollowEdgeNodeConfig) {
+ c := EdgeCoreConfig(config)
+
+ // use fake runtime service
+ edged.DefaultGetRuntimeService = GetFakeRuntimeAndImageServices
+
+ edged.Register(c.Modules.Edged)
+ edgehub.Register(c.Modules.EdgeHub, c.Modules.Edged.HostnameOverride)
+ metamanager.Register(c.Modules.MetaManager)
+
+ dbm.InitDBConfig(c.DataBase.DriverName, c.DataBase.AliasName, c.DataBase.DataSource)
+
+ // start all modules
+ core.Run()
+}
+
+func (c *hollowEdgeNodeConfig) addFlags(fs *pflag.FlagSet) {
+ fs.StringVar(&c.Token, "token", "", "Token indicates the priority of joining the cluster for the edge.")
+ fs.StringVar(&c.NodeName, "name", "fake-node", "Name of this Hollow Node.")
+ fs.StringVar(&c.WebsocketServer, "websocket-server", "", "Server indicates websocket server address.")
+ fs.StringVar(&c.HTTPServer, "http-server", "", "HTTPServer indicates the server for edge to apply for the certificate.")
+ bindableNodeLabels := cliflag.ConfigurationMap(c.NodeLabels)
+ fs.Var(&bindableNodeLabels, "node-labels", "Additional node labels")
+}
+
+func EdgeCoreConfig(config *hollowEdgeNodeConfig) *v1alpha1.EdgeCoreConfig {
+ edgeCoreConfig := v1alpha1.NewDefaultEdgeCoreConfig()
+
+ // overWrite config
+ edgeCoreConfig.DataBase.DataSource = "/edgecore.db"
+ edgeCoreConfig.Modules.EdgeHub.Token = config.Token
+ edgeCoreConfig.Modules.EdgeHub.HTTPServer = config.HTTPServer
+ edgeCoreConfig.Modules.EdgeHub.WebSocket.Server = config.WebsocketServer
+
+ // use fake runtime for test
+ edgeCoreConfig.Modules.Edged.RuntimeType = "fake"
+ edgeCoreConfig.Modules.Edged.RemoteRuntimeEndpoint = "/run/fake/fake.sock"
+ edgeCoreConfig.Modules.Edged.RemoteImageEndpoint = "/run/fake/fake.sock"
+ edgeCoreConfig.Modules.Edged.EnableMetrics = false
+
+ edgeCoreConfig.Modules.Edged.HostnameOverride = config.NodeName
+ edgeCoreConfig.Modules.Edged.Labels = config.NodeLabels
+
+ return edgeCoreConfig
+}
+
+func GetFakeRuntimeAndImageServices(
+ remoteRuntimeEndpoint,
+ remoteImageEndpoint string,
+ runtimeRequestTimeout metav1.Duration) (internalapi.RuntimeService, internalapi.ImageManagerService, error) {
+ endpoint, err := fakeremote.GenerateEndpoint()
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to generate fake endpoint %v", err)
+ }
+
+ fakeRemoteRuntime := fakeremote.NewFakeRemoteRuntime()
+ if err = fakeRemoteRuntime.Start(endpoint); err != nil {
+ return nil, nil, fmt.Errorf("failed to start fake runtime %v", err)
+ }
+
+ runtimeService, err := remote.NewRemoteRuntimeService(endpoint, 15*time.Second)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to init runtime service %v", err)
+ }
+
+ return runtimeService, fakeRemoteRuntime.ImageService, err
+}
diff --git a/edge/pkg/edged/edged.go b/edge/pkg/edged/edged.go
index 974674645..6039c1b8f 100644
--- a/edge/pkg/edged/edged.go
+++ b/edge/pkg/edged/edged.go
@@ -163,6 +163,13 @@ const (
ResolvConfDefault = "/etc/resolv.conf"
)
+type GetRuntimeServiceFunc func(
+ remoteRuntimeEndpoint,
+ remoteImageEndpoint string,
+ runtimeRequestTimeout metav1.Duration) (internalapi.RuntimeService, internalapi.ImageManagerService, error)
+
+var DefaultGetRuntimeService GetRuntimeServiceFunc = getRuntimeAndImageServices
+
// podReady holds the initPodReady flag and its lock
type podReady struct {
// initPodReady is flag to check Pod ready status
@@ -509,7 +516,7 @@ func newEdged(enable bool) (*edged, error) {
ResolvConfDefault)
httpClient := &http.Client{}
- runtimeService, imageService, err := getRuntimeAndImageServices(
+ runtimeService, imageService, err := DefaultGetRuntimeService(
edgedconfig.Config.RemoteRuntimeEndpoint,
edgedconfig.Config.RemoteImageEndpoint,
metav1.Duration{
@@ -518,6 +525,7 @@ func newEdged(enable bool) (*edged, error) {
if err != nil {
return nil, err
}
+
if ed.os == nil {
ed.os = kubecontainer.RealOS{}
}
diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh
index eaee5d42b..fe9288506 100755
--- a/hack/lib/golang.sh
+++ b/hack/lib/golang.sh
@@ -177,6 +177,7 @@ ALL_BINARIES_AND_TARGETS=(
edgesite-server:edgesite/cmd/edgesite-server
csidriver:cloud/cmd/csidriver
iptablesmanager:cloud/cmd/iptablesmanager
+ edgemark:edge/cmd/edgemark
)
kubeedge::golang::get_target_by_binary() {
diff --git a/hack/make-rules/crossbuildimage.sh b/hack/make-rules/crossbuildimage.sh
index 67f8d4e25..5d65b48b2 100755
--- a/hack/make-rules/crossbuildimage.sh
+++ b/hack/make-rules/crossbuildimage.sh
@@ -34,6 +34,7 @@ ALL_IMAGES_AND_TARGETS=(
edgesite-server:edgesite-server:build/edgesite/server-build.Dockerfile
csidriver:csidriver:build/csidriver/Dockerfile
iptablesmanager:iptables-manager:build/iptablesmanager/Dockerfile
+ edgemark:edgemark:build/edgemark/Dockerfile
)
function get_imagename_by_target() {
@@ -82,7 +83,7 @@ function build_multi_arch_images() {
DOCKERFILE_PATH="$(get_dockerfile_by_target ${arg})"
set -x
-
+
# If there's any issues when using buildx, can refer to the issue below
# https://github.com/docker/buildx/issues/495
# https://github.com/multiarch/qemu-user-static/issues/100
diff --git a/hack/make-rules/image.sh b/hack/make-rules/image.sh
index 49642be8b..f2067deed 100755
--- a/hack/make-rules/image.sh
+++ b/hack/make-rules/image.sh
@@ -31,6 +31,7 @@ ALL_IMAGES_AND_TARGETS=(
edgesite-server:edgesite-server:build/edgesite/server-build.Dockerfile
csidriver:csidriver:build/csidriver/Dockerfile
iptablesmanager:iptables-manager:build/iptablesmanager/Dockerfile
+ edgemark:edgemark:build/edgemark/Dockerfile
)
GO_LDFLAGS="$(${KUBEEDGE_ROOT}/hack/make-rules/version.sh)"
diff --git a/vendor/k8s.io/cri-api/pkg/apis/testing/fake_image_service.go b/vendor/k8s.io/cri-api/pkg/apis/testing/fake_image_service.go
new file mode 100644
index 000000000..17100abd3
--- /dev/null
+++ b/vendor/k8s.io/cri-api/pkg/apis/testing/fake_image_service.go
@@ -0,0 +1,230 @@
+/*
+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
+
+import (
+ "sync"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
+)
+
+// FakeImageService fakes the image service.
+type FakeImageService struct {
+ sync.Mutex
+
+ FakeImageSize uint64
+ Called []string
+ Errors map[string][]error
+ Images map[string]*runtimeapi.Image
+
+ pulledImages []*pulledImage
+
+ FakeFilesystemUsage []*runtimeapi.FilesystemUsage
+}
+
+// SetFakeImages sets the list of fake images for the 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] = r.makeFakeImage(
+ &runtimeapi.ImageSpec{
+ Image: image,
+ Annotations: make(map[string]string)})
+ }
+}
+
+// SetFakeImagesWithAnnotations sets the list of fake images for the FakeImageService with annotations.
+func (r *FakeImageService) SetFakeImagesWithAnnotations(imageSpecs []*runtimeapi.ImageSpec) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Images = make(map[string]*runtimeapi.Image)
+ for _, imageSpec := range imageSpecs {
+ r.Images[imageSpec.Image] = r.makeFakeImage(imageSpec)
+ }
+}
+
+// SetFakeImageSize sets the image size for the FakeImageService.
+func (r *FakeImageService) SetFakeImageSize(size uint64) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.FakeImageSize = size
+}
+
+// SetFakeFilesystemUsage sets the FilesystemUsage for FakeImageService.
+func (r *FakeImageService) SetFakeFilesystemUsage(usage []*runtimeapi.FilesystemUsage) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.FakeFilesystemUsage = usage
+}
+
+// NewFakeImageService creates a new FakeImageService.
+func NewFakeImageService() *FakeImageService {
+ return &FakeImageService{
+ Called: make([]string, 0),
+ Errors: make(map[string][]error),
+ Images: make(map[string]*runtimeapi.Image),
+ }
+}
+
+func (r *FakeImageService) makeFakeImage(image *runtimeapi.ImageSpec) *runtimeapi.Image {
+ return &runtimeapi.Image{
+ Id: image.Image,
+ Size_: r.FakeImageSize,
+ Spec: image,
+ RepoTags: []string{image.Image},
+ }
+}
+
+// stringInSlice returns true if s is in list
+func stringInSlice(s string, list []string) bool {
+ for _, v := range list {
+ if v == s {
+ return true
+ }
+ }
+
+ return false
+}
+
+// InjectError sets the error message for the FakeImageService.
+func (r *FakeImageService) InjectError(f string, err error) {
+ r.Lock()
+ defer r.Unlock()
+ r.Errors[f] = append(r.Errors[f], err)
+}
+
+// caller of popError must grab a lock.
+func (r *FakeImageService) popError(f string) error {
+ if r.Errors == nil {
+ return nil
+ }
+ errs := r.Errors[f]
+ if len(errs) == 0 {
+ return nil
+ }
+ err, errs := errs[0], errs[1:]
+ r.Errors[f] = errs
+ return err
+}
+
+// ListImages returns the list of images from FakeImageService or error if it was previously set.
+func (r *FakeImageService) ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ListImages")
+ if err := r.popError("ListImages"); err != nil {
+ return nil, err
+ }
+
+ images := make([]*runtimeapi.Image, 0)
+ for _, img := range r.Images {
+ if filter != nil && filter.Image != nil {
+ if !stringInSlice(filter.Image.Image, img.RepoTags) {
+ continue
+ }
+ }
+
+ images = append(images, img)
+ }
+ return images, nil
+}
+
+// ImageStatus returns the status of the image from the FakeImageService.
+func (r *FakeImageService) ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.Image, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ImageStatus")
+ if err := r.popError("ImageStatus"); err != nil {
+ return nil, err
+ }
+
+ return r.Images[image.Image], nil
+}
+
+// PullImage emulate pulling the image from the FakeImageService.
+func (r *FakeImageService) PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "PullImage")
+ if err := r.popError("PullImage"); err != nil {
+ return "", err
+ }
+
+ r.pulledImages = append(r.pulledImages, &pulledImage{imageSpec: image, authConfig: auth})
+ // ImageID should be randomized for real container runtime, but here just use
+ // image's name for easily making fake images.
+ imageID := image.Image
+ if _, ok := r.Images[imageID]; !ok {
+ r.Images[imageID] = r.makeFakeImage(image)
+ }
+
+ return imageID, nil
+}
+
+// RemoveImage removes image from the FakeImageService.
+func (r *FakeImageService) RemoveImage(image *runtimeapi.ImageSpec) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "RemoveImage")
+ if err := r.popError("RemoveImage"); err != nil {
+ return err
+ }
+
+ // Remove the image
+ delete(r.Images, image.Image)
+
+ return nil
+}
+
+// ImageFsInfo returns information of the filesystem that is used to store images.
+func (r *FakeImageService) ImageFsInfo() ([]*runtimeapi.FilesystemUsage, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ImageFsInfo")
+ if err := r.popError("ImageFsInfo"); err != nil {
+ return nil, err
+ }
+
+ return r.FakeFilesystemUsage, nil
+}
+
+// AssertImagePulledWithAuth validates whether the image was pulled with auth and asserts if it wasn't.
+func (r *FakeImageService) AssertImagePulledWithAuth(t *testing.T, image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig, failMsg string) {
+ r.Lock()
+ defer r.Unlock()
+ expected := &pulledImage{imageSpec: image, authConfig: auth}
+ assert.Contains(t, r.pulledImages, expected, failMsg)
+}
+
+type pulledImage struct {
+ imageSpec *runtimeapi.ImageSpec
+ authConfig *runtimeapi.AuthConfig
+}
diff --git a/vendor/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go b/vendor/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go
new file mode 100644
index 000000000..dff770f4a
--- /dev/null
+++ b/vendor/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go
@@ -0,0 +1,636 @@
+/*
+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
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+ "time"
+
+ runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
+)
+
+var (
+ // FakeVersion is a version of a fake runtime.
+ FakeVersion = "0.1.0"
+
+ // FakeRuntimeName is the name of the fake runtime.
+ FakeRuntimeName = "fakeRuntime"
+
+ // FakePodSandboxIPs is an IP address of the fake runtime.
+ FakePodSandboxIPs = []string{"192.168.192.168"}
+)
+
+// FakePodSandbox is the fake implementation of runtimeapi.PodSandboxStatus.
+type FakePodSandbox struct {
+ // PodSandboxStatus contains the runtime information for a sandbox.
+ runtimeapi.PodSandboxStatus
+ // RuntimeHandler is the runtime handler that was issued with the RunPodSandbox request.
+ RuntimeHandler string
+}
+
+// FakeContainer is a fake container.
+type FakeContainer struct {
+ // ContainerStatus contains the runtime information for a container.
+ runtimeapi.ContainerStatus
+
+ // LinuxResources contains the resources specific to linux containers.
+ LinuxResources *runtimeapi.LinuxContainerResources
+
+ // the sandbox id of this container
+ SandboxID string
+}
+
+// FakeRuntimeService is a fake runetime service.
+type FakeRuntimeService struct {
+ sync.Mutex
+
+ Called []string
+ Errors map[string][]error
+
+ FakeStatus *runtimeapi.RuntimeStatus
+ Containers map[string]*FakeContainer
+ Sandboxes map[string]*FakePodSandbox
+ FakeContainerStats map[string]*runtimeapi.ContainerStats
+
+ ErrorOnSandboxCreate bool
+}
+
+// GetContainerID returns the unique container ID from the FakeRuntimeService.
+func (r *FakeRuntimeService) GetContainerID(sandboxID, name string, attempt uint32) (string, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ for id, c := range r.Containers {
+ if c.SandboxID == sandboxID && c.Metadata.Name == name && c.Metadata.Attempt == attempt {
+ return id, nil
+ }
+ }
+ return "", fmt.Errorf("container (name, attempt, sandboxID)=(%q, %d, %q) not found", name, attempt, sandboxID)
+}
+
+// SetFakeSandboxes sets the fake sandboxes for the FakeRuntimeService.
+func (r *FakeRuntimeService) SetFakeSandboxes(sandboxes []*FakePodSandbox) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Sandboxes = make(map[string]*FakePodSandbox)
+ for _, sandbox := range sandboxes {
+ sandboxID := sandbox.Id
+ r.Sandboxes[sandboxID] = sandbox
+ }
+}
+
+// SetFakeContainers sets fake containers for the FakeRuntimeService.
+func (r *FakeRuntimeService) SetFakeContainers(containers []*FakeContainer) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Containers = make(map[string]*FakeContainer)
+ for _, c := range containers {
+ containerID := c.Id
+ r.Containers[containerID] = c
+ }
+
+}
+
+// AssertCalls validates whether specified calls were made to the FakeRuntimeService.
+func (r *FakeRuntimeService) AssertCalls(calls []string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ if !reflect.DeepEqual(calls, r.Called) {
+ return fmt.Errorf("expected %#v, got %#v", calls, r.Called)
+ }
+ return nil
+}
+
+// GetCalls returns the list of calls made to the FakeRuntimeService.
+func (r *FakeRuntimeService) GetCalls() []string {
+ r.Lock()
+ defer r.Unlock()
+ return append([]string{}, r.Called...)
+}
+
+// InjectError inject the error to the next call to the FakeRuntimeService.
+func (r *FakeRuntimeService) InjectError(f string, err error) {
+ r.Lock()
+ defer r.Unlock()
+ r.Errors[f] = append(r.Errors[f], err)
+}
+
+// caller of popError must grab a lock.
+func (r *FakeRuntimeService) popError(f string) error {
+ if r.Errors == nil {
+ return nil
+ }
+ errs := r.Errors[f]
+ if len(errs) == 0 {
+ return nil
+ }
+ err, errs := errs[0], errs[1:]
+ r.Errors[f] = errs
+ return err
+}
+
+// NewFakeRuntimeService creates a new FakeRuntimeService.
+func NewFakeRuntimeService() *FakeRuntimeService {
+ return &FakeRuntimeService{
+ Called: make([]string, 0),
+ Errors: make(map[string][]error),
+ Containers: make(map[string]*FakeContainer),
+ Sandboxes: make(map[string]*FakePodSandbox),
+ FakeContainerStats: make(map[string]*runtimeapi.ContainerStats),
+ }
+}
+
+// Version returns version information from the FakeRuntimeService.
+func (r *FakeRuntimeService) Version(apiVersion string) (*runtimeapi.VersionResponse, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "Version")
+ if err := r.popError("Version"); err != nil {
+ return nil, err
+ }
+
+ return &runtimeapi.VersionResponse{
+ Version: FakeVersion,
+ RuntimeName: FakeRuntimeName,
+ RuntimeVersion: FakeVersion,
+ RuntimeApiVersion: FakeVersion,
+ }, nil
+}
+
+// Status returns runtime status of the FakeRuntimeService.
+func (r *FakeRuntimeService) Status() (*runtimeapi.RuntimeStatus, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "Status")
+ if err := r.popError("Status"); err != nil {
+ return nil, err
+ }
+
+ return r.FakeStatus, nil
+}
+
+// RunPodSandbox emulates the run of the pod sandbox in the FakeRuntimeService.
+func (r *FakeRuntimeService) RunPodSandbox(config *runtimeapi.PodSandboxConfig, runtimeHandler string) (string, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "RunPodSandbox")
+ if err := r.popError("RunPodSandbox"); err != nil {
+ return "", err
+ }
+
+ if r.ErrorOnSandboxCreate {
+ return "", fmt.Errorf("error on sandbox create")
+ }
+
+ // PodSandboxID should be randomized for real container runtime, but here just use
+ // fixed name from BuildSandboxName() for easily making fake sandboxes.
+ podSandboxID := BuildSandboxName(config.Metadata)
+ createdAt := time.Now().UnixNano()
+ r.Sandboxes[podSandboxID] = &FakePodSandbox{
+ PodSandboxStatus: runtimeapi.PodSandboxStatus{
+ Id: podSandboxID,
+ Metadata: config.Metadata,
+ State: runtimeapi.PodSandboxState_SANDBOX_READY,
+ CreatedAt: createdAt,
+ Network: &runtimeapi.PodSandboxNetworkStatus{
+ Ip: FakePodSandboxIPs[0],
+ },
+ // Without setting sandboxStatus's Linux.Namespaces.Options, kubeGenericRuntimeManager's podSandboxChanged will consider it as network
+ // namespace changed and always recreate sandbox which causes pod creation failed.
+ // Ref `sandboxStatus.GetLinux().GetNamespaces().GetOptions().GetNetwork() != networkNamespaceForPod(pod)` in podSandboxChanged function.
+ Linux: &runtimeapi.LinuxPodSandboxStatus{
+ Namespaces: &runtimeapi.Namespace{
+ Options: config.GetLinux().GetSecurityContext().GetNamespaceOptions(),
+ },
+ },
+ Labels: config.Labels,
+ Annotations: config.Annotations,
+ RuntimeHandler: runtimeHandler,
+ },
+ RuntimeHandler: runtimeHandler,
+ }
+ // assign additional IPs
+ additionalIPs := FakePodSandboxIPs[1:]
+ additionalPodIPs := make([]*runtimeapi.PodIP, 0, len(additionalIPs))
+ for _, ip := range additionalIPs {
+ additionalPodIPs = append(additionalPodIPs, &runtimeapi.PodIP{
+ Ip: ip,
+ })
+ }
+ r.Sandboxes[podSandboxID].PodSandboxStatus.Network.AdditionalIps = additionalPodIPs
+ return podSandboxID, nil
+}
+
+// StopPodSandbox emulates the stop of pod sandbox in the FakeRuntimeService.
+func (r *FakeRuntimeService) StopPodSandbox(podSandboxID string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "StopPodSandbox")
+ if err := r.popError("StopPodSandbox"); err != nil {
+ return err
+ }
+
+ if s, ok := r.Sandboxes[podSandboxID]; ok {
+ s.State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY
+ } else {
+ return fmt.Errorf("pod sandbox %s not found", podSandboxID)
+ }
+
+ return nil
+}
+
+// RemovePodSandbox emulates removal of the pod sadbox in the FakeRuntimeService.
+func (r *FakeRuntimeService) RemovePodSandbox(podSandboxID string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "RemovePodSandbox")
+ if err := r.popError("RemovePodSandbox"); err != nil {
+ return err
+ }
+
+ // Remove the pod sandbox
+ delete(r.Sandboxes, podSandboxID)
+
+ return nil
+}
+
+// PodSandboxStatus returns pod sandbox status from the FakeRuntimeService.
+func (r *FakeRuntimeService) PodSandboxStatus(podSandboxID string) (*runtimeapi.PodSandboxStatus, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "PodSandboxStatus")
+ if err := r.popError("PodSandboxStatus"); err != nil {
+ return nil, err
+ }
+
+ s, ok := r.Sandboxes[podSandboxID]
+ if !ok {
+ return nil, fmt.Errorf("pod sandbox %q not found", podSandboxID)
+ }
+
+ status := s.PodSandboxStatus
+ return &status, nil
+}
+
+// ListPodSandbox returns the list of pod sandboxes in the FakeRuntimeService.
+func (r *FakeRuntimeService) ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]*runtimeapi.PodSandbox, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ListPodSandbox")
+ if err := r.popError("ListPodSandbox"); err != nil {
+ return nil, err
+ }
+
+ result := make([]*runtimeapi.PodSandbox, 0)
+ for id, s := range r.Sandboxes {
+ if filter != nil {
+ if filter.Id != "" && filter.Id != id {
+ continue
+ }
+ if filter.State != nil && filter.GetState().State != s.State {
+ continue
+ }
+ if filter.LabelSelector != nil && !filterInLabels(filter.LabelSelector, s.GetLabels()) {
+ continue
+ }
+ }
+
+ result = append(result, &runtimeapi.PodSandbox{
+ Id: s.Id,
+ Metadata: s.Metadata,
+ State: s.State,
+ CreatedAt: s.CreatedAt,
+ Labels: s.Labels,
+ Annotations: s.Annotations,
+ RuntimeHandler: s.RuntimeHandler,
+ })
+ }
+
+ return result, nil
+}
+
+// PortForward emulates the set up of port forward in the FakeRuntimeService.
+func (r *FakeRuntimeService) PortForward(*runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "PortForward")
+ if err := r.popError("PortForward"); err != nil {
+ return nil, err
+ }
+
+ return &runtimeapi.PortForwardResponse{}, nil
+}
+
+// CreateContainer emulates container creation in the FakeRuntimeService.
+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")
+ if err := r.popError("CreateContainer"); err != nil {
+ return "", err
+ }
+
+ // ContainerID should be randomized for real container runtime, but here just use
+ // fixed BuildContainerName() for easily making fake containers.
+ containerID := BuildContainerName(config.Metadata, podSandboxID)
+ createdAt := time.Now().UnixNano()
+ createdState := runtimeapi.ContainerState_CONTAINER_CREATED
+ imageRef := config.Image.Image
+ r.Containers[containerID] = &FakeContainer{
+ ContainerStatus: runtimeapi.ContainerStatus{
+ Id: containerID,
+ Metadata: config.Metadata,
+ Image: config.Image,
+ ImageRef: imageRef,
+ CreatedAt: createdAt,
+ State: createdState,
+ Labels: config.Labels,
+ Annotations: config.Annotations,
+ },
+ SandboxID: podSandboxID,
+ LinuxResources: config.GetLinux().GetResources(),
+ }
+
+ return containerID, nil
+}
+
+// StartContainer emulates start of a container in the FakeRuntimeService.
+func (r *FakeRuntimeService) StartContainer(containerID string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "StartContainer")
+ if err := r.popError("StartContainer"); err != nil {
+ return err
+ }
+
+ c, ok := r.Containers[containerID]
+ if !ok {
+ return fmt.Errorf("container %s not found", containerID)
+ }
+
+ // Set container to running.
+ c.State = runtimeapi.ContainerState_CONTAINER_RUNNING
+ c.StartedAt = time.Now().UnixNano()
+
+ return nil
+}
+
+// StopContainer emulates stop of a container in the FakeRuntimeService.
+func (r *FakeRuntimeService) StopContainer(containerID string, timeout int64) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "StopContainer")
+ if err := r.popError("StopContainer"); err != nil {
+ return err
+ }
+
+ c, ok := r.Containers[containerID]
+ if !ok {
+ return fmt.Errorf("container %q not found", containerID)
+ }
+
+ // Set container to exited state.
+ finishedAt := time.Now().UnixNano()
+ exitedState := runtimeapi.ContainerState_CONTAINER_EXITED
+ c.State = exitedState
+ c.FinishedAt = finishedAt
+
+ return nil
+}
+
+// RemoveContainer emulates remove of a container in the FakeRuntimeService.
+func (r *FakeRuntimeService) RemoveContainer(containerID string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "RemoveContainer")
+ if err := r.popError("RemoveContainer"); err != nil {
+ return err
+ }
+
+ // Remove the container
+ delete(r.Containers, containerID)
+
+ return nil
+}
+
+// ListContainers returns the list of containers in the FakeRuntimeService.
+func (r *FakeRuntimeService) ListContainers(filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ListContainers")
+ if err := r.popError("ListContainers"); err != nil {
+ return nil, err
+ }
+
+ result := make([]*runtimeapi.Container, 0)
+ for _, s := range r.Containers {
+ if filter != nil {
+ if filter.Id != "" && filter.Id != s.Id {
+ continue
+ }
+ if filter.PodSandboxId != "" && filter.PodSandboxId != s.SandboxID {
+ continue
+ }
+ if filter.State != nil && filter.GetState().State != s.State {
+ continue
+ }
+ if filter.LabelSelector != nil && !filterInLabels(filter.LabelSelector, s.GetLabels()) {
+ continue
+ }
+ }
+
+ result = append(result, &runtimeapi.Container{
+ Id: s.Id,
+ CreatedAt: s.CreatedAt,
+ PodSandboxId: s.SandboxID,
+ Metadata: s.Metadata,
+ State: s.State,
+ Image: s.Image,
+ ImageRef: s.ImageRef,
+ Labels: s.Labels,
+ Annotations: s.Annotations,
+ })
+ }
+
+ return result, nil
+}
+
+// ContainerStatus returns the container status given the container ID in FakeRuntimeService.
+func (r *FakeRuntimeService) ContainerStatus(containerID string) (*runtimeapi.ContainerStatus, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ContainerStatus")
+ if err := r.popError("ContainerStatus"); err != nil {
+ return nil, err
+ }
+
+ c, ok := r.Containers[containerID]
+ if !ok {
+ return nil, fmt.Errorf("container %q not found", containerID)
+ }
+
+ status := c.ContainerStatus
+ return &status, nil
+}
+
+// UpdateContainerResources returns the container resource in the FakeRuntimeService.
+func (r *FakeRuntimeService) UpdateContainerResources(string, *runtimeapi.LinuxContainerResources) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "UpdateContainerResources")
+ return r.popError("UpdateContainerResources")
+}
+
+// ExecSync emulates the sync execution of a command in a container in the FakeRuntimeService.
+func (r *FakeRuntimeService) ExecSync(containerID string, cmd []string, timeout time.Duration) (stdout []byte, stderr []byte, err error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ExecSync")
+ err = r.popError("ExecSync")
+ return
+}
+
+// Exec emulates the execution of a command in a container in the FakeRuntimeService.
+func (r *FakeRuntimeService) Exec(*runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "Exec")
+ if err := r.popError("Exec"); err != nil {
+ return nil, err
+ }
+
+ return &runtimeapi.ExecResponse{}, nil
+}
+
+// Attach emulates the attach request in the FakeRuntimeService.
+func (r *FakeRuntimeService) Attach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "Attach")
+ if err := r.popError("Attach"); err != nil {
+ return nil, err
+ }
+
+ return &runtimeapi.AttachResponse{}, nil
+}
+
+// UpdateRuntimeConfig emulates the update of a runtime config for the FakeRuntimeService.
+func (r *FakeRuntimeService) UpdateRuntimeConfig(runtimeCOnfig *runtimeapi.RuntimeConfig) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "UpdateRuntimeConfig")
+ return r.popError("UpdateRuntimeConfig")
+}
+
+// SetFakeContainerStats sets the fake container stats in the FakeRuntimeService.
+func (r *FakeRuntimeService) SetFakeContainerStats(containerStats []*runtimeapi.ContainerStats) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.FakeContainerStats = make(map[string]*runtimeapi.ContainerStats)
+ for _, s := range containerStats {
+ r.FakeContainerStats[s.Attributes.Id] = s
+ }
+}
+
+// ContainerStats returns the container stats in the FakeRuntimeService.
+func (r *FakeRuntimeService) ContainerStats(containerID string) (*runtimeapi.ContainerStats, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ContainerStats")
+ if err := r.popError("ContainerStats"); err != nil {
+ return nil, err
+ }
+
+ s, found := r.FakeContainerStats[containerID]
+ if !found {
+ return nil, fmt.Errorf("no stats for container %q", containerID)
+ }
+ return s, nil
+}
+
+// ListContainerStats returns the list of all container stats given the filter in the FakeRuntimeService.
+func (r *FakeRuntimeService) ListContainerStats(filter *runtimeapi.ContainerStatsFilter) ([]*runtimeapi.ContainerStats, error) {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ListContainerStats")
+ if err := r.popError("ListContainerStats"); err != nil {
+ return nil, err
+ }
+
+ var result []*runtimeapi.ContainerStats
+ for _, c := range r.Containers {
+ if filter != nil {
+ if filter.Id != "" && filter.Id != c.Id {
+ continue
+ }
+ if filter.PodSandboxId != "" && filter.PodSandboxId != c.SandboxID {
+ continue
+ }
+ if filter.LabelSelector != nil && !filterInLabels(filter.LabelSelector, c.GetLabels()) {
+ continue
+ }
+ }
+ s, found := r.FakeContainerStats[c.Id]
+ if !found {
+ continue
+ }
+ result = append(result, s)
+ }
+
+ return result, nil
+}
+
+// ReopenContainerLog emulates call to the reopen container log in the FakeRuntimeService.
+func (r *FakeRuntimeService) ReopenContainerLog(containerID string) error {
+ r.Lock()
+ defer r.Unlock()
+
+ r.Called = append(r.Called, "ReopenContainerLog")
+
+ if err := r.popError("ReopenContainerLog"); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/k8s.io/cri-api/pkg/apis/testing/utils.go b/vendor/k8s.io/cri-api/pkg/apis/testing/utils.go
new file mode 100644
index 000000000..5b3814e9d
--- /dev/null
+++ b/vendor/k8s.io/cri-api/pkg/apis/testing/utils.go
@@ -0,0 +1,48 @@
+/*
+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
+
+import (
+ "fmt"
+
+ runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
+)
+
+// BuildContainerName creates a unique container name string.
+func BuildContainerName(metadata *runtimeapi.ContainerMetadata, sandboxID string) string {
+ // include the sandbox ID to make the container ID unique.
+ return fmt.Sprintf("%s_%s_%d", sandboxID, metadata.Name, metadata.Attempt)
+}
+
+// BuildSandboxName creates a unique sandbox name string.
+func BuildSandboxName(metadata *runtimeapi.PodSandboxMetadata) string {
+ return fmt.Sprintf("%s_%s_%s_%d", metadata.Name, metadata.Namespace, metadata.Uid, metadata.Attempt)
+}
+
+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
+}
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/doc.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/doc.go
new file mode 100644
index 000000000..fc92f3c76
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2017 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 fake containers a fake gRPC implementation of internalapi.RuntimeService
+// and internalapi.ImageManagerService.
+package fake
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint.go
new file mode 100644
index 000000000..52ef573bf
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint.go
@@ -0,0 +1,34 @@
+// +build !windows
+
+/*
+Copyright 2017 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 fake
+
+import (
+ "fmt"
+ "k8s.io/apimachinery/pkg/util/rand"
+)
+
+const (
+ defaultUnixEndpoint = "unix:///tmp/kubelet_remote_%v.sock"
+)
+
+// GenerateEndpoint generates a new unix socket server of grpc server.
+func GenerateEndpoint() (string, error) {
+ // use random int be a part fo file name
+ return fmt.Sprintf(defaultUnixEndpoint, rand.Int()), nil
+}
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint_windows.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint_windows.go
new file mode 100644
index 000000000..cb43296bc
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/endpoint_windows.go
@@ -0,0 +1,40 @@
+// +build windows
+
+/*
+Copyright 2017 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 fake
+
+import (
+ "fmt"
+ "net"
+)
+
+// GenerateEndpoint generates a new tcp endpoint of grpc server.
+func GenerateEndpoint() (string, error) {
+ addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
+ if err != nil {
+ return "", nil
+ }
+
+ l, err := net.ListenTCP("tcp", addr)
+ if err != nil {
+ return "", err
+ }
+
+ defer l.Close()
+ return fmt.Sprintf("tcp://127.0.0.1:%d", l.Addr().(*net.TCPAddr).Port), nil
+}
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_image_service.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_image_service.go
new file mode 100644
index 000000000..c85f9ecf9
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_image_service.go
@@ -0,0 +1,81 @@
+/*
+Copyright 2017 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 fake
+
+import (
+ "context"
+
+ kubeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
+)
+
+// ListImages lists existing images.
+func (f *RemoteRuntime) ListImages(ctx context.Context, req *kubeapi.ListImagesRequest) (*kubeapi.ListImagesResponse, error) {
+ images, err := f.ImageService.ListImages(req.Filter)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ListImagesResponse{
+ Images: images,
+ }, nil
+}
+
+// ImageStatus returns the status of the image. If the image is not
+// present, returns a response with ImageStatusResponse.Image set to
+// nil.
+func (f *RemoteRuntime) ImageStatus(ctx context.Context, req *kubeapi.ImageStatusRequest) (*kubeapi.ImageStatusResponse, error) {
+ status, err := f.ImageService.ImageStatus(req.Image)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ImageStatusResponse{Image: status}, nil
+}
+
+// PullImage pulls an image with authentication config.
+func (f *RemoteRuntime) PullImage(ctx context.Context, req *kubeapi.PullImageRequest) (*kubeapi.PullImageResponse, error) {
+ image, err := f.ImageService.PullImage(req.Image, req.Auth, req.SandboxConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.PullImageResponse{
+ ImageRef: image,
+ }, nil
+}
+
+// RemoveImage removes the image.
+// This call is idempotent, and must not return an error if the image has
+// already been removed.
+func (f *RemoteRuntime) RemoveImage(ctx context.Context, req *kubeapi.RemoveImageRequest) (*kubeapi.RemoveImageResponse, error) {
+ err := f.ImageService.RemoveImage(req.Image)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.RemoveImageResponse{}, nil
+}
+
+// ImageFsInfo returns information of the filesystem that is used to store images.
+func (f *RemoteRuntime) ImageFsInfo(ctx context.Context, req *kubeapi.ImageFsInfoRequest) (*kubeapi.ImageFsInfoResponse, error) {
+ fsUsage, err := f.ImageService.ImageFsInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ImageFsInfoResponse{ImageFilesystems: fsUsage}, nil
+}
diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_runtime.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_runtime.go
new file mode 100644
index 000000000..e49f311aa
--- /dev/null
+++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cri/remote/fake/fake_runtime.go
@@ -0,0 +1,303 @@
+/*
+Copyright 2017 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 fake
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "google.golang.org/grpc"
+ kubeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
+ apitest "k8s.io/cri-api/pkg/apis/testing"
+ "k8s.io/kubernetes/pkg/kubelet/cri/remote/util"
+ utilexec "k8s.io/utils/exec"
+)
+
+// RemoteRuntime represents a fake remote container runtime.
+type RemoteRuntime struct {
+ server *grpc.Server
+ // Fake runtime service.
+ RuntimeService *apitest.FakeRuntimeService
+ // Fake image service.
+ ImageService *apitest.FakeImageService
+}
+
+// NewFakeRemoteRuntime creates a new RemoteRuntime.
+func NewFakeRemoteRuntime() *RemoteRuntime {
+ fakeRuntimeService := apitest.NewFakeRuntimeService()
+ fakeImageService := apitest.NewFakeImageService()
+
+ f := &RemoteRuntime{
+ server: grpc.NewServer(),
+ RuntimeService: fakeRuntimeService,
+ ImageService: fakeImageService,
+ }
+ kubeapi.RegisterRuntimeServiceServer(f.server, f)
+ kubeapi.RegisterImageServiceServer(f.server, f)
+
+ return f
+}
+
+// Start starts the fake remote runtime.
+func (f *RemoteRuntime) Start(endpoint string) error {
+ l, err := util.CreateListener(endpoint)
+ if err != nil {
+ return fmt.Errorf("failed to listen on %q: %v", endpoint, err)
+ }
+
+ go f.server.Serve(l)
+
+ // Set runtime and network conditions ready.
+ f.RuntimeService.FakeStatus = &kubeapi.RuntimeStatus{
+ Conditions: []*kubeapi.RuntimeCondition{
+ {Type: kubeapi.RuntimeReady, Status: true},
+ {Type: kubeapi.NetworkReady, Status: true},
+ },
+ }
+
+ return nil
+}
+
+// Stop stops the fake remote runtime.
+func (f *RemoteRuntime) Stop() {
+ f.server.Stop()
+}
+
+// Version returns the runtime name, runtime version, and runtime API version.
+func (f *RemoteRuntime) Version(ctx context.Context, req *kubeapi.VersionRequest) (*kubeapi.VersionResponse, error) {
+ return f.RuntimeService.Version(req.Version)
+}
+
+// RunPodSandbox creates and starts a pod-level sandbox. Runtimes must ensure
+// the sandbox is in the ready state on success.
+func (f *RemoteRuntime) RunPodSandbox(ctx context.Context, req *kubeapi.RunPodSandboxRequest) (*kubeapi.RunPodSandboxResponse, error) {
+ sandboxID, err := f.RuntimeService.RunPodSandbox(req.Config, req.RuntimeHandler)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.RunPodSandboxResponse{PodSandboxId: sandboxID}, nil
+}
+
+// StopPodSandbox stops any running process that is part of the sandbox and
+// reclaims network resources (e.g., IP addresses) allocated to the sandbox.
+// If there are any running containers in the sandbox, they must be forcibly
+// terminated.
+func (f *RemoteRuntime) StopPodSandbox(ctx context.Context, req *kubeapi.StopPodSandboxRequest) (*kubeapi.StopPodSandboxResponse, error) {
+ err := f.RuntimeService.StopPodSandbox(req.PodSandboxId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.StopPodSandboxResponse{}, nil
+}
+
+// RemovePodSandbox removes the sandbox. If there are any running containers
+// in the sandbox, they must be forcibly terminated and removed.
+// This call is idempotent, and must not return an error if the sandbox has
+// already been removed.
+func (f *RemoteRuntime) RemovePodSandbox(ctx context.Context, req *kubeapi.RemovePodSandboxRequest) (*kubeapi.RemovePodSandboxResponse, error) {
+ err := f.RuntimeService.StopPodSandbox(req.PodSandboxId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.RemovePodSandboxResponse{}, nil
+}
+
+// PodSandboxStatus returns the status of the PodSandbox. If the PodSandbox is not
+// present, returns an error.
+func (f *RemoteRuntime) PodSandboxStatus(ctx context.Context, req *kubeapi.PodSandboxStatusRequest) (*kubeapi.PodSandboxStatusResponse, error) {
+ podStatus, err := f.RuntimeService.PodSandboxStatus(req.PodSandboxId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.PodSandboxStatusResponse{Status: podStatus}, nil
+}
+
+// ListPodSandbox returns a list of PodSandboxes.
+func (f *RemoteRuntime) ListPodSandbox(ctx context.Context, req *kubeapi.ListPodSandboxRequest) (*kubeapi.ListPodSandboxResponse, error) {
+ items, err := f.RuntimeService.ListPodSandbox(req.Filter)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ListPodSandboxResponse{Items: items}, nil
+}
+
+// CreateContainer creates a new container in specified PodSandbox
+func (f *RemoteRuntime) CreateContainer(ctx context.Context, req *kubeapi.CreateContainerRequest) (*kubeapi.CreateContainerResponse, error) {
+ containerID, err := f.RuntimeService.CreateContainer(req.PodSandboxId, req.Config, req.SandboxConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.CreateContainerResponse{ContainerId: containerID}, nil
+}
+
+// StartContainer starts the container.
+func (f *RemoteRuntime) StartContainer(ctx context.Context, req *kubeapi.StartContainerRequest) (*kubeapi.StartContainerResponse, error) {
+ err := f.RuntimeService.StartContainer(req.ContainerId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.StartContainerResponse{}, nil
+}
+
+// StopContainer stops a running container with a grace period (i.e., timeout).
+// This call is idempotent, and must not return an error if the container has
+// already been stopped.
+func (f *RemoteRuntime) StopContainer(ctx context.Context, req *kubeapi.StopContainerRequest) (*kubeapi.StopContainerResponse, error) {
+ err := f.RuntimeService.StopContainer(req.ContainerId, req.Timeout)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.StopContainerResponse{}, nil
+}
+
+// RemoveContainer removes the container. If the container is running, the
+// container must be forcibly removed.
+// This call is idempotent, and must not return an error if the container has
+// already been removed.
+func (f *RemoteRuntime) RemoveContainer(ctx context.Context, req *kubeapi.RemoveContainerRequest) (*kubeapi.RemoveContainerResponse, error) {
+ err := f.RuntimeService.RemoveContainer(req.ContainerId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.RemoveContainerResponse{}, nil
+}
+
+// ListContainers lists all containers by filters.
+func (f *RemoteRuntime) ListContainers(ctx context.Context, req *kubeapi.ListContainersRequest) (*kubeapi.ListContainersResponse, error) {
+ items, err := f.RuntimeService.ListContainers(req.Filter)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ListContainersResponse{Containers: items}, nil
+}
+
+// ContainerStatus returns status of the container. If the container is not
+// present, returns an error.
+func (f *RemoteRuntime) ContainerStatus(ctx context.Context, req *kubeapi.ContainerStatusRequest) (*kubeapi.ContainerStatusResponse, error) {
+ status, err := f.RuntimeService.ContainerStatus(req.ContainerId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ContainerStatusResponse{Status: status}, nil
+}
+
+// ExecSync runs a command in a container synchronously.
+func (f *RemoteRuntime) ExecSync(ctx context.Context, req *kubeapi.ExecSyncRequest) (*kubeapi.ExecSyncResponse, error) {
+ var exitCode int32
+ stdout, stderr, err := f.RuntimeService.ExecSync(req.ContainerId, req.Cmd, time.Duration(req.Timeout)*time.Second)
+ if err != nil {
+ exitError, ok := err.(utilexec.ExitError)
+ if !ok {
+ return nil, err
+ }
+ exitCode = int32(exitError.ExitStatus())
+ }
+
+ return &kubeapi.ExecSyncResponse{
+ Stdout: stdout,
+ Stderr: stderr,
+ ExitCode: exitCode,
+ }, nil
+}
+
+// Exec prepares a streaming endpoint to execute a command in the container.
+func (f *RemoteRuntime) Exec(ctx context.Context, req *kubeapi.ExecRequest) (*kubeapi.ExecResponse, error) {
+ return f.RuntimeService.Exec(req)
+}
+
+// Attach prepares a streaming endpoint to attach to a running container.
+func (f *RemoteRuntime) Attach(ctx context.Context, req *kubeapi.AttachRequest) (*kubeapi.AttachResponse, error) {
+ return f.RuntimeService.Attach(req)
+}
+
+// PortForward prepares a streaming endpoint to forward ports from a PodSandbox.
+func (f *RemoteRuntime) PortForward(ctx context.Context, req *kubeapi.PortForwardRequest) (*kubeapi.PortForwardResponse, error) {
+ return f.RuntimeService.PortForward(req)
+}
+
+// ContainerStats returns stats of the container. If the container does not
+// exist, the call returns an error.
+func (f *RemoteRuntime) ContainerStats(ctx context.Context, req *kubeapi.ContainerStatsRequest) (*kubeapi.ContainerStatsResponse, error) {
+ stats, err := f.RuntimeService.ContainerStats(req.ContainerId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ContainerStatsResponse{Stats: stats}, nil
+}
+
+// ListContainerStats returns stats of all running containers.
+func (f *RemoteRuntime) ListContainerStats(ctx context.Context, req *kubeapi.ListContainerStatsRequest) (*kubeapi.ListContainerStatsResponse, error) {
+ stats, err := f.RuntimeService.ListContainerStats(req.Filter)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ListContainerStatsResponse{Stats: stats}, nil
+}
+
+// UpdateRuntimeConfig updates the runtime configuration based on the given request.
+func (f *RemoteRuntime) UpdateRuntimeConfig(ctx context.Context, req *kubeapi.UpdateRuntimeConfigRequest) (*kubeapi.UpdateRuntimeConfigResponse, error) {
+ err := f.RuntimeService.UpdateRuntimeConfig(req.RuntimeConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.UpdateRuntimeConfigResponse{}, nil
+}
+
+// Status returns the status of the runtime.
+func (f *RemoteRuntime) Status(ctx context.Context, req *kubeapi.StatusRequest) (*kubeapi.StatusResponse, error) {
+ status, err := f.RuntimeService.Status()
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.StatusResponse{Status: status}, nil
+}
+
+// UpdateContainerResources updates ContainerConfig of the container.
+func (f *RemoteRuntime) UpdateContainerResources(ctx context.Context, req *kubeapi.UpdateContainerResourcesRequest) (*kubeapi.UpdateContainerResourcesResponse, error) {
+ err := f.RuntimeService.UpdateContainerResources(req.ContainerId, req.Linux)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.UpdateContainerResourcesResponse{}, nil
+}
+
+// ReopenContainerLog reopens the container log file.
+func (f *RemoteRuntime) ReopenContainerLog(ctx context.Context, req *kubeapi.ReopenContainerLogRequest) (*kubeapi.ReopenContainerLogResponse, error) {
+ err := f.RuntimeService.ReopenContainerLog(req.ContainerId)
+ if err != nil {
+ return nil, err
+ }
+
+ return &kubeapi.ReopenContainerLogResponse{}, nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e4d19c035..22ce229fd 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1625,6 +1625,7 @@ k8s.io/component-helpers/storage/volume
## explicit
k8s.io/cri-api/pkg/apis
k8s.io/cri-api/pkg/apis/runtime/v1alpha2
+k8s.io/cri-api/pkg/apis/testing
# k8s.io/csi-translation-lib v0.22.6
## explicit
k8s.io/csi-translation-lib
@@ -1819,6 +1820,7 @@ k8s.io/kubernetes/pkg/kubelet/configmap
k8s.io/kubernetes/pkg/kubelet/container
k8s.io/kubernetes/pkg/kubelet/container/testing
k8s.io/kubernetes/pkg/kubelet/cri/remote
+k8s.io/kubernetes/pkg/kubelet/cri/remote/fake
k8s.io/kubernetes/pkg/kubelet/cri/remote/util
k8s.io/kubernetes/pkg/kubelet/cri/streaming
k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward