From 39e56578ee4d6f51db0ac818befc95d3b23f20b2 Mon Sep 17 00:00:00 2001 From: l1b0k Date: Mon, 25 Mar 2024 14:37:26 +0800 Subject: [PATCH] controlplane: allow update podNetwokring Signed-off-by: l1b0k --- .github/workflows/check.yml | 4 +- Makefile | 111 ++++++ .../terway-controlplane.go | 2 +- daemon/config.go | 2 +- daemon/config_test.go | 2 +- daemon/daemon.go | 2 +- go.mod | 6 +- go.sum | 4 - pkg/aliyun/client/interface.go | 3 + pkg/aliyun/client/interface_default.go | 2 + pkg/aliyun/client/mocks/ECS.go | 324 ++++++++++++++++ pkg/aliyun/client/mocks/EFLO.go | 59 +++ pkg/aliyun/client/mocks/VPC.go | 59 +++ pkg/controller/common/types_default.go | 2 +- pkg/controller/mocks/Interface.go | 356 ++++++++++++++++++ pkg/controller/node/node_controller.go | 2 +- pkg/controller/node/node_controller_test.go | 94 +++++ pkg/controller/node/suite_test.go | 84 +++++ pkg/controller/pod-networking/networking.go | 5 +- .../pod-networking/networking_test.go | 72 +++- pkg/controller/pod-networking/predict.go | 18 +- pkg/controller/pod-networking/predict_test.go | 47 +++ pkg/controller/pod-networking/suite_test.go | 62 +-- pkg/controller/pod/pod_controller.go | 2 +- pkg/controller/pod/pod_controller_default.go | 2 +- pkg/controller/pod/pod_controller_test.go | 2 +- pkg/controller/pod/suite_test.go | 13 +- pkg/controller/pool/eni_mgr.go | 2 +- pkg/controller/pool/eni_mgr_test.go | 3 +- pkg/controller/register.go | 4 +- pkg/factory/aliyun/aliyun.go | 2 +- pkg/factory/aliyun/eflo.go | 2 +- pkg/{controller => }/vswitch/vswitch.go | 0 pkg/{controller => }/vswitch/vswitch_test.go | 3 +- plugin/driver/utils/utils_linux_test.go | 17 +- types/config.go | 2 +- types/controlplane/config.go | 5 +- 37 files changed, 1280 insertions(+), 101 deletions(-) create mode 100644 Makefile create mode 100644 pkg/aliyun/client/mocks/ECS.go create mode 100644 pkg/aliyun/client/mocks/EFLO.go create mode 100644 pkg/aliyun/client/mocks/VPC.go create mode 100644 pkg/controller/mocks/Interface.go create mode 100644 pkg/controller/node/node_controller_test.go create mode 100644 pkg/controller/node/suite_test.go create mode 100644 pkg/controller/pod-networking/predict_test.go rename pkg/{controller => }/vswitch/vswitch.go (100%) rename pkg/{controller => }/vswitch/vswitch_test.go (99%) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index a8d2267f..3ea0da8b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -19,9 +19,7 @@ jobs: - name: Test run: | go=$(which go) - sudo $go test -tags default_build,privileged -v ./... - sudo $go test -tags default_build,privileged -race -v ./... - sudo $go test -tags default_build,privileged -coverpkg=./... -race -coverprofile=coverage.txt -covermode=atomic ./... + sudo make test - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..fbb4ffa0 --- /dev/null +++ b/Makefile @@ -0,0 +1,111 @@ + +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. +ENVTEST_K8S_VERSION = 1.29.0 + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +GO_BUILD_TAGS ?= default_build,privileged + +# Setting SHELL to bash allows bash commands to be executed by recipes. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec + +.PHONY: all +all: build + +##@ General + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Development + +.PHONY: manifests +manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./pkg/apis/..." output:crd:artifacts:config=pkg/apis/crds + +.PHONY: generate +generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./pkg/apis/..." + +.PHONY: fmt +fmt: ## Run go fmt against code. + go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code. + GOOS=linux go vet --tags "$(GO_BUILD_TAGS)" ./... + +.PHONY: test +test: manifests generate fmt vet envtest ## Run tests. + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -race --tags "$(GO_BUILD_TAGS)" $$(go list ./... | grep -v '/e2e|/mocks') -coverprofile coverage.txt + +.PHONY: lint +lint: golangci-lint ## Run golangci-lint linter & yamllint + $(GOLANGCI_LINT) run + +.PHONY: lint-fix +lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes + $(GOLANGCI_LINT) run + +##@ Build + +.PHONY: build +build: manifests generate fmt vet ## Build manager binary. + go build --tags "$(GO_BUILD_TAGS)" -o bin/terwayd cmd/terway/main.go + go build --tags "$(GO_BUILD_TAGS)" -o bin/terway-controlplane cmd/terway-controlplane/terway-controlplane.go + go build --tags "$(GO_BUILD_TAGS)" -o bin/terway-cli ./cmd/terway-cli/ + +##@ Dependencies + +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +## Tool Binaries +KUBECTL ?= kubectl +CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION) +ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION) +GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION) + +## Tool Versions +CONTROLLER_TOOLS_VERSION ?= v0.14.0 +ENVTEST_VERSION ?= latest +GOLANGCI_LINT_VERSION ?= v1.54.2 + +.PHONY: controller-gen +controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. +$(CONTROLLER_GEN): $(LOCALBIN) + $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION)) + +.PHONY: envtest +envtest: $(ENVTEST) ## Download setup-envtest locally if necessary. +$(ENVTEST): $(LOCALBIN) + $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION)) + +.PHONY: golangci-lint +golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. +$(GOLANGCI_LINT): $(LOCALBIN) + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION}) + +# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist +# $1 - target path with name of binary (ideally with version) +# $2 - package url which can be installed +# $3 - specific version of package +define go-install-tool +@[ -f $(1) ] || { \ +set -e; \ +package=$(2)@$(3) ;\ +echo "Downloading $${package}" ;\ +GOBIN=$(LOCALBIN) go install $${package} ;\ +mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\ +} +endef diff --git a/cmd/terway-controlplane/terway-controlplane.go b/cmd/terway-controlplane/terway-controlplane.go index 71b0c218..f8e6a194 100644 --- a/cmd/terway-controlplane/terway-controlplane.go +++ b/cmd/terway-controlplane/terway-controlplane.go @@ -40,12 +40,12 @@ import ( register "github.com/AliyunContainerService/terway/pkg/controller" _ "github.com/AliyunContainerService/terway/pkg/controller/all" "github.com/AliyunContainerService/terway/pkg/controller/delegate" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/controller/webhook" "github.com/AliyunContainerService/terway/pkg/metric" "github.com/AliyunContainerService/terway/pkg/utils" "github.com/AliyunContainerService/terway/pkg/utils/k8sclient" "github.com/AliyunContainerService/terway/pkg/version" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types/controlplane" ) diff --git a/daemon/config.go b/daemon/config.go index 0f239dbd..60750831 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -5,9 +5,9 @@ import ( "github.com/AliyunContainerService/terway/pkg/aliyun/client" "github.com/AliyunContainerService/terway/pkg/aliyun/instance" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/k8s" "github.com/AliyunContainerService/terway/pkg/utils" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/daemon" ) diff --git a/daemon/config_test.go b/daemon/config_test.go index 71988ef5..ba5122c3 100644 --- a/daemon/config_test.go +++ b/daemon/config_test.go @@ -7,7 +7,7 @@ import ( "github.com/AliyunContainerService/terway/pkg/aliyun/client" "github.com/AliyunContainerService/terway/pkg/aliyun/instance" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/daemon" ) diff --git a/daemon/daemon.go b/daemon/daemon.go index 58c8eb06..07a5fa23 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -22,7 +22,6 @@ import ( "github.com/AliyunContainerService/terway/pkg/apis/alibabacloud.com/v1beta1" "github.com/AliyunContainerService/terway/pkg/apis/crds" "github.com/AliyunContainerService/terway/pkg/backoff" - vswpool "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/eni" "github.com/AliyunContainerService/terway/pkg/factory" "github.com/AliyunContainerService/terway/pkg/factory/aliyun" @@ -32,6 +31,7 @@ import ( "github.com/AliyunContainerService/terway/pkg/tracing" "github.com/AliyunContainerService/terway/pkg/utils" "github.com/AliyunContainerService/terway/pkg/utils/nodecap" + vswpool "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/rpc" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/daemon" diff --git a/go.mod b/go.mod index 85d977a6..1f3c3c06 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/go-playground/mold/v4 v4.2.0 github.com/go-playground/validator/v10 v10.11.1 github.com/google/uuid v1.3.0 - github.com/onsi/ginkgo v1.16.5 + github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.7 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.15.1 @@ -73,12 +73,14 @@ require ( github.com/go-openapi/swag v0.22.3 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/gookit/color v1.5.3 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect @@ -95,7 +97,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nxadm/tail v1.4.8 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect @@ -123,7 +124,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect diff --git a/go.sum b/go.sum index 2168bda9..322e9521 100644 --- a/go.sum +++ b/go.sum @@ -605,7 +605,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -619,8 +618,6 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= @@ -1264,7 +1261,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/aliyun/client/interface.go b/pkg/aliyun/client/interface.go index 30c00453..9e0953d9 100644 --- a/pkg/aliyun/client/interface.go +++ b/pkg/aliyun/client/interface.go @@ -1,3 +1,6 @@ +//go:generate mockery --name VPC --tags default_build +//go:generate mockery --name EFLO --tags default_build + package client import ( diff --git a/pkg/aliyun/client/interface_default.go b/pkg/aliyun/client/interface_default.go index 77f73a4c..2c1a2b9d 100644 --- a/pkg/aliyun/client/interface_default.go +++ b/pkg/aliyun/client/interface_default.go @@ -1,5 +1,7 @@ //go:build default_build +//go:generate mockery --name ECS --tags default_build + package client import ( diff --git a/pkg/aliyun/client/mocks/ECS.go b/pkg/aliyun/client/mocks/ECS.go new file mode 100644 index 00000000..4d24b703 --- /dev/null +++ b/pkg/aliyun/client/mocks/ECS.go @@ -0,0 +1,324 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + client "github.com/AliyunContainerService/terway/pkg/aliyun/client" + + ecs "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" + + mock "github.com/stretchr/testify/mock" + + netip "net/netip" + + wait "k8s.io/apimachinery/pkg/util/wait" +) + +// ECS is an autogenerated mock type for the ECS type +type ECS struct { + mock.Mock +} + +// AssignIpv6Addresses provides a mock function with given fields: ctx, eniID, count, idempotentKey +func (_m *ECS) AssignIpv6Addresses(ctx context.Context, eniID string, count int, idempotentKey string) ([]netip.Addr, error) { + ret := _m.Called(ctx, eniID, count, idempotentKey) + + if len(ret) == 0 { + panic("no return value specified for AssignIpv6Addresses") + } + + var r0 []netip.Addr + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) ([]netip.Addr, error)); ok { + return rf(ctx, eniID, count, idempotentKey) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) []netip.Addr); ok { + r0 = rf(ctx, eniID, count, idempotentKey) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]netip.Addr) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int, string) error); ok { + r1 = rf(ctx, eniID, count, idempotentKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AssignPrivateIPAddress provides a mock function with given fields: ctx, eniID, count, idempotent +func (_m *ECS) AssignPrivateIPAddress(ctx context.Context, eniID string, count int, idempotent string) ([]netip.Addr, error) { + ret := _m.Called(ctx, eniID, count, idempotent) + + if len(ret) == 0 { + panic("no return value specified for AssignPrivateIPAddress") + } + + var r0 []netip.Addr + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) ([]netip.Addr, error)); ok { + return rf(ctx, eniID, count, idempotent) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) []netip.Addr); ok { + r0 = rf(ctx, eniID, count, idempotent) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]netip.Addr) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int, string) error); ok { + r1 = rf(ctx, eniID, count, idempotent) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AttachNetworkInterface provides a mock function with given fields: ctx, eniID, instanceID, trunkENIID +func (_m *ECS) AttachNetworkInterface(ctx context.Context, eniID string, instanceID string, trunkENIID string) error { + ret := _m.Called(ctx, eniID, instanceID, trunkENIID) + + if len(ret) == 0 { + panic("no return value specified for AttachNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok { + r0 = rf(ctx, eniID, instanceID, trunkENIID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CreateNetworkInterface provides a mock function with given fields: ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags +func (_m *ECS) CreateNetworkInterface(ctx context.Context, trunk bool, erdma bool, vSwitchID string, securityGroups []string, resourceGroupID string, ipCount int, ipv6Count int, eniTags map[string]string) (*client.NetworkInterface, error) { + ret := _m.Called(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + + if len(ret) == 0 { + panic("no return value specified for CreateNetworkInterface") + } + + var r0 *client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) (*client.NetworkInterface, error)); ok { + return rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } + if rf, ok := ret.Get(0).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) *client.NetworkInterface); ok { + r0 = rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) error); ok { + r1 = rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteNetworkInterface provides a mock function with given fields: ctx, eniID +func (_m *ECS) DeleteNetworkInterface(ctx context.Context, eniID string) error { + ret := _m.Called(ctx, eniID) + + if len(ret) == 0 { + panic("no return value specified for DeleteNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, eniID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeInstanceTypes provides a mock function with given fields: ctx, types +func (_m *ECS) DescribeInstanceTypes(ctx context.Context, types []string) ([]ecs.InstanceType, error) { + ret := _m.Called(ctx, types) + + if len(ret) == 0 { + panic("no return value specified for DescribeInstanceTypes") + } + + var r0 []ecs.InstanceType + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]ecs.InstanceType, error)); ok { + return rf(ctx, types) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []ecs.InstanceType); ok { + r0 = rf(ctx, types) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ecs.InstanceType) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, types) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeNetworkInterface provides a mock function with given fields: ctx, vpcID, eniID, instanceID, instanceType, status, tags +func (_m *ECS) DescribeNetworkInterface(ctx context.Context, vpcID string, eniID []string, instanceID string, instanceType string, status string, tags map[string]string) ([]*client.NetworkInterface, error) { + ret := _m.Called(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + + if len(ret) == 0 { + panic("no return value specified for DescribeNetworkInterface") + } + + var r0 []*client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string, string, string, string, map[string]string) ([]*client.NetworkInterface, error)); ok { + return rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []string, string, string, string, map[string]string) []*client.NetworkInterface); ok { + r0 = rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []string, string, string, string, map[string]string) error); ok { + r1 = rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DetachNetworkInterface provides a mock function with given fields: ctx, eniID, instanceID, trunkENIID +func (_m *ECS) DetachNetworkInterface(ctx context.Context, eniID string, instanceID string, trunkENIID string) error { + ret := _m.Called(ctx, eniID, instanceID, trunkENIID) + + if len(ret) == 0 { + panic("no return value specified for DetachNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok { + r0 = rf(ctx, eniID, instanceID, trunkENIID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ModifyNetworkInterfaceAttribute provides a mock function with given fields: ctx, eniID, securityGroupIDs +func (_m *ECS) ModifyNetworkInterfaceAttribute(ctx context.Context, eniID string, securityGroupIDs []string) error { + ret := _m.Called(ctx, eniID, securityGroupIDs) + + if len(ret) == 0 { + panic("no return value specified for ModifyNetworkInterfaceAttribute") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok { + r0 = rf(ctx, eniID, securityGroupIDs) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnAssignIpv6Addresses provides a mock function with given fields: ctx, eniID, ips +func (_m *ECS) UnAssignIpv6Addresses(ctx context.Context, eniID string, ips []netip.Addr) error { + ret := _m.Called(ctx, eniID, ips) + + if len(ret) == 0 { + panic("no return value specified for UnAssignIpv6Addresses") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []netip.Addr) error); ok { + r0 = rf(ctx, eniID, ips) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnAssignPrivateIPAddresses provides a mock function with given fields: ctx, eniID, ips +func (_m *ECS) UnAssignPrivateIPAddresses(ctx context.Context, eniID string, ips []netip.Addr) error { + ret := _m.Called(ctx, eniID, ips) + + if len(ret) == 0 { + panic("no return value specified for UnAssignPrivateIPAddresses") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []netip.Addr) error); ok { + r0 = rf(ctx, eniID, ips) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// WaitForNetworkInterface provides a mock function with given fields: ctx, eniID, status, backoff, ignoreNotExist +func (_m *ECS) WaitForNetworkInterface(ctx context.Context, eniID string, status string, backoff wait.Backoff, ignoreNotExist bool) (*client.NetworkInterface, error) { + ret := _m.Called(ctx, eniID, status, backoff, ignoreNotExist) + + if len(ret) == 0 { + panic("no return value specified for WaitForNetworkInterface") + } + + var r0 *client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, wait.Backoff, bool) (*client.NetworkInterface, error)); ok { + return rf(ctx, eniID, status, backoff, ignoreNotExist) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string, wait.Backoff, bool) *client.NetworkInterface); ok { + r0 = rf(ctx, eniID, status, backoff, ignoreNotExist) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string, wait.Backoff, bool) error); ok { + r1 = rf(ctx, eniID, status, backoff, ignoreNotExist) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewECS creates a new instance of ECS. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewECS(t interface { + mock.TestingT + Cleanup(func()) +}) *ECS { + mock := &ECS{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/aliyun/client/mocks/EFLO.go b/pkg/aliyun/client/mocks/EFLO.go new file mode 100644 index 00000000..c2e003ef --- /dev/null +++ b/pkg/aliyun/client/mocks/EFLO.go @@ -0,0 +1,59 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + eflo "github.com/aliyun/alibaba-cloud-sdk-go/services/eflo" + mock "github.com/stretchr/testify/mock" +) + +// EFLO is an autogenerated mock type for the EFLO type +type EFLO struct { + mock.Mock +} + +// GetNodeInfoForPod provides a mock function with given fields: ctx, nodeID +func (_m *EFLO) GetNodeInfoForPod(ctx context.Context, nodeID string) (*eflo.Content, error) { + ret := _m.Called(ctx, nodeID) + + if len(ret) == 0 { + panic("no return value specified for GetNodeInfoForPod") + } + + var r0 *eflo.Content + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (*eflo.Content, error)); ok { + return rf(ctx, nodeID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) *eflo.Content); ok { + r0 = rf(ctx, nodeID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*eflo.Content) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, nodeID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewEFLO creates a new instance of EFLO. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEFLO(t interface { + mock.TestingT + Cleanup(func()) +}) *EFLO { + mock := &EFLO{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/aliyun/client/mocks/VPC.go b/pkg/aliyun/client/mocks/VPC.go new file mode 100644 index 00000000..0f7eaf1f --- /dev/null +++ b/pkg/aliyun/client/mocks/VPC.go @@ -0,0 +1,59 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + vpc "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" + mock "github.com/stretchr/testify/mock" +) + +// VPC is an autogenerated mock type for the VPC type +type VPC struct { + mock.Mock +} + +// DescribeVSwitchByID provides a mock function with given fields: ctx, vSwitchID +func (_m *VPC) DescribeVSwitchByID(ctx context.Context, vSwitchID string) (*vpc.VSwitch, error) { + ret := _m.Called(ctx, vSwitchID) + + if len(ret) == 0 { + panic("no return value specified for DescribeVSwitchByID") + } + + var r0 *vpc.VSwitch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (*vpc.VSwitch, error)); ok { + return rf(ctx, vSwitchID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) *vpc.VSwitch); ok { + r0 = rf(ctx, vSwitchID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*vpc.VSwitch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, vSwitchID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewVPC creates a new instance of VPC. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewVPC(t interface { + mock.TestingT + Cleanup(func()) +}) *VPC { + mock := &VPC{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/controller/common/types_default.go b/pkg/controller/common/types_default.go index f6477617..54677525 100644 --- a/pkg/controller/common/types_default.go +++ b/pkg/controller/common/types_default.go @@ -47,6 +47,6 @@ func NewNodeInfo(node *corev1.Node) (*NodeInfo, error) { res.ZoneID = zone return res, nil } - return nil, fmt.Errorf("cat not found zone label from node %s", node.Name) + return nil, fmt.Errorf("can not found zone label from node %s", node.Name) } diff --git a/pkg/controller/mocks/Interface.go b/pkg/controller/mocks/Interface.go new file mode 100644 index 00000000..ce28cdd3 --- /dev/null +++ b/pkg/controller/mocks/Interface.go @@ -0,0 +1,356 @@ +// Code generated by mockery v2.42.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + client "github.com/AliyunContainerService/terway/pkg/aliyun/client" + + ecs "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" + + mock "github.com/stretchr/testify/mock" + + netip "net/netip" + + vpc "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" + + wait "k8s.io/apimachinery/pkg/util/wait" +) + +// Interface is an autogenerated mock type for the Interface type +type Interface struct { + mock.Mock +} + +// AssignIpv6Addresses provides a mock function with given fields: ctx, eniID, count, idempotentKey +func (_m *Interface) AssignIpv6Addresses(ctx context.Context, eniID string, count int, idempotentKey string) ([]netip.Addr, error) { + ret := _m.Called(ctx, eniID, count, idempotentKey) + + if len(ret) == 0 { + panic("no return value specified for AssignIpv6Addresses") + } + + var r0 []netip.Addr + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) ([]netip.Addr, error)); ok { + return rf(ctx, eniID, count, idempotentKey) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) []netip.Addr); ok { + r0 = rf(ctx, eniID, count, idempotentKey) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]netip.Addr) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int, string) error); ok { + r1 = rf(ctx, eniID, count, idempotentKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AssignPrivateIPAddress provides a mock function with given fields: ctx, eniID, count, idempotent +func (_m *Interface) AssignPrivateIPAddress(ctx context.Context, eniID string, count int, idempotent string) ([]netip.Addr, error) { + ret := _m.Called(ctx, eniID, count, idempotent) + + if len(ret) == 0 { + panic("no return value specified for AssignPrivateIPAddress") + } + + var r0 []netip.Addr + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) ([]netip.Addr, error)); ok { + return rf(ctx, eniID, count, idempotent) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int, string) []netip.Addr); ok { + r0 = rf(ctx, eniID, count, idempotent) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]netip.Addr) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int, string) error); ok { + r1 = rf(ctx, eniID, count, idempotent) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AttachNetworkInterface provides a mock function with given fields: ctx, eniID, instanceID, trunkENIID +func (_m *Interface) AttachNetworkInterface(ctx context.Context, eniID string, instanceID string, trunkENIID string) error { + ret := _m.Called(ctx, eniID, instanceID, trunkENIID) + + if len(ret) == 0 { + panic("no return value specified for AttachNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok { + r0 = rf(ctx, eniID, instanceID, trunkENIID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CreateNetworkInterface provides a mock function with given fields: ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags +func (_m *Interface) CreateNetworkInterface(ctx context.Context, trunk bool, erdma bool, vSwitchID string, securityGroups []string, resourceGroupID string, ipCount int, ipv6Count int, eniTags map[string]string) (*client.NetworkInterface, error) { + ret := _m.Called(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + + if len(ret) == 0 { + panic("no return value specified for CreateNetworkInterface") + } + + var r0 *client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) (*client.NetworkInterface, error)); ok { + return rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } + if rf, ok := ret.Get(0).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) *client.NetworkInterface); ok { + r0 = rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, bool, bool, string, []string, string, int, int, map[string]string) error); ok { + r1 = rf(ctx, trunk, erdma, vSwitchID, securityGroups, resourceGroupID, ipCount, ipv6Count, eniTags) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteNetworkInterface provides a mock function with given fields: ctx, eniID +func (_m *Interface) DeleteNetworkInterface(ctx context.Context, eniID string) error { + ret := _m.Called(ctx, eniID) + + if len(ret) == 0 { + panic("no return value specified for DeleteNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, eniID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeInstanceTypes provides a mock function with given fields: ctx, types +func (_m *Interface) DescribeInstanceTypes(ctx context.Context, types []string) ([]ecs.InstanceType, error) { + ret := _m.Called(ctx, types) + + if len(ret) == 0 { + panic("no return value specified for DescribeInstanceTypes") + } + + var r0 []ecs.InstanceType + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]ecs.InstanceType, error)); ok { + return rf(ctx, types) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []ecs.InstanceType); ok { + r0 = rf(ctx, types) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ecs.InstanceType) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, types) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeNetworkInterface provides a mock function with given fields: ctx, vpcID, eniID, instanceID, instanceType, status, tags +func (_m *Interface) DescribeNetworkInterface(ctx context.Context, vpcID string, eniID []string, instanceID string, instanceType string, status string, tags map[string]string) ([]*client.NetworkInterface, error) { + ret := _m.Called(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + + if len(ret) == 0 { + panic("no return value specified for DescribeNetworkInterface") + } + + var r0 []*client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string, string, string, string, map[string]string) ([]*client.NetworkInterface, error)); ok { + return rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []string, string, string, string, map[string]string) []*client.NetworkInterface); ok { + r0 = rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []string, string, string, string, map[string]string) error); ok { + r1 = rf(ctx, vpcID, eniID, instanceID, instanceType, status, tags) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeVSwitchByID provides a mock function with given fields: ctx, vSwitchID +func (_m *Interface) DescribeVSwitchByID(ctx context.Context, vSwitchID string) (*vpc.VSwitch, error) { + ret := _m.Called(ctx, vSwitchID) + + if len(ret) == 0 { + panic("no return value specified for DescribeVSwitchByID") + } + + var r0 *vpc.VSwitch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (*vpc.VSwitch, error)); ok { + return rf(ctx, vSwitchID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) *vpc.VSwitch); ok { + r0 = rf(ctx, vSwitchID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*vpc.VSwitch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, vSwitchID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DetachNetworkInterface provides a mock function with given fields: ctx, eniID, instanceID, trunkENIID +func (_m *Interface) DetachNetworkInterface(ctx context.Context, eniID string, instanceID string, trunkENIID string) error { + ret := _m.Called(ctx, eniID, instanceID, trunkENIID) + + if len(ret) == 0 { + panic("no return value specified for DetachNetworkInterface") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok { + r0 = rf(ctx, eniID, instanceID, trunkENIID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ModifyNetworkInterfaceAttribute provides a mock function with given fields: ctx, eniID, securityGroupIDs +func (_m *Interface) ModifyNetworkInterfaceAttribute(ctx context.Context, eniID string, securityGroupIDs []string) error { + ret := _m.Called(ctx, eniID, securityGroupIDs) + + if len(ret) == 0 { + panic("no return value specified for ModifyNetworkInterfaceAttribute") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok { + r0 = rf(ctx, eniID, securityGroupIDs) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnAssignIpv6Addresses provides a mock function with given fields: ctx, eniID, ips +func (_m *Interface) UnAssignIpv6Addresses(ctx context.Context, eniID string, ips []netip.Addr) error { + ret := _m.Called(ctx, eniID, ips) + + if len(ret) == 0 { + panic("no return value specified for UnAssignIpv6Addresses") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []netip.Addr) error); ok { + r0 = rf(ctx, eniID, ips) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnAssignPrivateIPAddresses provides a mock function with given fields: ctx, eniID, ips +func (_m *Interface) UnAssignPrivateIPAddresses(ctx context.Context, eniID string, ips []netip.Addr) error { + ret := _m.Called(ctx, eniID, ips) + + if len(ret) == 0 { + panic("no return value specified for UnAssignPrivateIPAddresses") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []netip.Addr) error); ok { + r0 = rf(ctx, eniID, ips) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// WaitForNetworkInterface provides a mock function with given fields: ctx, eniID, status, backoff, ignoreNotExist +func (_m *Interface) WaitForNetworkInterface(ctx context.Context, eniID string, status string, backoff wait.Backoff, ignoreNotExist bool) (*client.NetworkInterface, error) { + ret := _m.Called(ctx, eniID, status, backoff, ignoreNotExist) + + if len(ret) == 0 { + panic("no return value specified for WaitForNetworkInterface") + } + + var r0 *client.NetworkInterface + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, wait.Backoff, bool) (*client.NetworkInterface, error)); ok { + return rf(ctx, eniID, status, backoff, ignoreNotExist) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string, wait.Backoff, bool) *client.NetworkInterface); ok { + r0 = rf(ctx, eniID, status, backoff, ignoreNotExist) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*client.NetworkInterface) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string, wait.Backoff, bool) error); ok { + r1 = rf(ctx, eniID, status, backoff, ignoreNotExist) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewInterface creates a new instance of Interface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *Interface { + mock := &Interface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/controller/node/node_controller.go b/pkg/controller/node/node_controller.go index 8ce244d8..49a91ef5 100644 --- a/pkg/controller/node/node_controller.go +++ b/pkg/controller/node/node_controller.go @@ -13,7 +13,7 @@ import ( register "github.com/AliyunContainerService/terway/pkg/controller" "github.com/AliyunContainerService/terway/pkg/controller/common" eni_pool "github.com/AliyunContainerService/terway/pkg/controller/pool" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/controlplane" "github.com/AliyunContainerService/terway/types/daemon" diff --git a/pkg/controller/node/node_controller_test.go b/pkg/controller/node/node_controller_test.go new file mode 100644 index 00000000..5273c2f5 --- /dev/null +++ b/pkg/controller/node/node_controller_test.go @@ -0,0 +1,94 @@ +/* +Copyright 2024. + +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 node + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + vswpool "github.com/AliyunContainerService/terway/pkg/vswitch" + "github.com/AliyunContainerService/terway/types/controlplane" +) + +var _ = Describe("Node Controller", func() { + Context("no-op", func() { + const resourceName = "test-resource" + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + } + node := &corev1.Node{} + + BeforeEach(func() { + By("creating the custom resource for the Kind Node") + err := k8sClient.Get(ctx, typeNamespacedName, node) + if err != nil && errors.IsNotFound(err) { + resource := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Labels: map[string]string{ + "topology.kubernetes.io/zone": "cn-hangzhou-k", + "topology.kubernetes.io/region": "cn-hangzhou", + }, + }, + Spec: corev1.NodeSpec{ + ProviderID: "cn-hangzhou.instance-id", + }, + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterEach(func() { + resource := &corev1.Node{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance Node") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + + switchPool, err := vswpool.NewSwitchPool(100, "10m") + Expect(err).NotTo(HaveOccurred()) + + disable := false + controlplane.SetConfig(&controlplane.Config{EnableTrunk: &disable}) + + It("should successfully reconcile the resource", func() { + controllerReconciler := &ReconcileNode{ + client: k8sClient, + swPool: switchPool, + aliyun: openAPI, + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + }) + }) +}) diff --git a/pkg/controller/node/suite_test.go b/pkg/controller/node/suite_test.go new file mode 100644 index 00000000..f28b9c0c --- /dev/null +++ b/pkg/controller/node/suite_test.go @@ -0,0 +1,84 @@ +/* +Copyright 2024. + +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 node + +import ( + "fmt" + "path/filepath" + "runtime" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/AliyunContainerService/terway/pkg/controller/mocks" +) + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var openAPI *mocks.Interface + +func TestControllers(t *testing.T) { + RegisterFailHandler(Fail) + + openAPI = mocks.NewInterface(t) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "apis", "crds")}, + ErrorIfCRDPathMissing: true, + BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", + fmt.Sprintf("1.29.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = corev1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/pkg/controller/pod-networking/networking.go b/pkg/controller/pod-networking/networking.go index 2cf5e966..40b988f3 100644 --- a/pkg/controller/pod-networking/networking.go +++ b/pkg/controller/pod-networking/networking.go @@ -23,14 +23,13 @@ import ( aliyunClient "github.com/AliyunContainerService/terway/pkg/aliyun/client" "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" register "github.com/AliyunContainerService/terway/pkg/controller" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/utils" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" @@ -70,7 +69,6 @@ var _ reconcile.Reconciler = &ReconcilePodNetworking{} // ReconcilePodNetworking reconciles a AutoRepair object type ReconcilePodNetworking struct { client client.Client - scheme *runtime.Scheme aliyunClient aliyunClient.VPC swPool *vswitch.SwitchPool @@ -82,7 +80,6 @@ type ReconcilePodNetworking struct { func NewReconcilePodNetworking(mgr manager.Manager, aliyunClient aliyunClient.VPC, swPool *vswitch.SwitchPool) *ReconcilePodNetworking { r := &ReconcilePodNetworking{ client: mgr.GetClient(), - scheme: mgr.GetScheme(), record: mgr.GetEventRecorderFor("PodNetworking"), aliyunClient: aliyunClient, swPool: swPool, diff --git a/pkg/controller/pod-networking/networking_test.go b/pkg/controller/pod-networking/networking_test.go index 066003e0..e39769c9 100644 --- a/pkg/controller/pod-networking/networking_test.go +++ b/pkg/controller/pod-networking/networking_test.go @@ -1,28 +1,35 @@ -//go:build test_env - package podnetworking import ( "context" + "fmt" "time" - . "github.com/onsi/ginkgo" + "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/stretchr/testify/mock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/reconcile" networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" + vswpool "github.com/AliyunContainerService/terway/pkg/vswitch" ) var _ = Describe("Networking controller", func() { Context("Create normal", func() { name := "normal-podnetworking" - key := types.NamespacedName{Name: name} + typeNamespacedName := types.NamespacedName{ + Name: name, + } + ctx := context.Background() It("Should create successfully", func() { created := &networkv1beta1.PodNetworking{ ObjectMeta: metav1.ObjectMeta{ - Name: key.Name, + Name: typeNamespacedName.Name, }, Spec: networkv1beta1.PodNetworkingSpec{ AllocationType: networkv1beta1.AllocationType{}, @@ -32,10 +39,34 @@ var _ = Describe("Networking controller", func() { } Expect(k8sClient.Create(context.Background(), created)).Should(Succeed()) }) + + switchPool, err := vswpool.NewSwitchPool(100, "10m") + Expect(err).NotTo(HaveOccurred()) + + openAPI.On("DescribeVSwitchByID", mock.Anything, "vsw-1").Return(&vpc.VSwitch{ + AvailableIpAddressCount: 100, + VSwitchId: "vsw-1", + ZoneId: "cn-hangzhou-k", + }, nil) + + It("should successfully reconcile the resource", func() { + controllerReconciler := &ReconcilePodNetworking{ + client: k8sClient, + aliyunClient: openAPI, + swPool: switchPool, + record: record.NewFakeRecorder(100), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + }) + It("Status Should Be Ready", func() { created := &networkv1beta1.PodNetworking{} Eventually(func(g Gomega) networkv1beta1.NetworkingStatus { - err := k8sClient.Get(context.Background(), key, created) + err := k8sClient.Get(context.Background(), typeNamespacedName, created) g.Expect(err).NotTo(HaveOccurred()) return created.Status.Status }, 5*time.Second, 500*time.Millisecond).Should(Equal(networkv1beta1.NetworkingStatusReady)) @@ -44,11 +75,14 @@ var _ = Describe("Networking controller", func() { Context("Create with not exist vSwitch", func() { name := "abnormal-podnetworking" - key := types.NamespacedName{Name: name} + typeNamespacedName := types.NamespacedName{ + Name: name, + } + ctx := context.Background() It("Should create successfully", func() { created := &networkv1beta1.PodNetworking{ ObjectMeta: metav1.ObjectMeta{ - Name: key.Name, + Name: typeNamespacedName.Name, }, Spec: networkv1beta1.PodNetworkingSpec{ AllocationType: networkv1beta1.AllocationType{}, @@ -58,10 +92,30 @@ var _ = Describe("Networking controller", func() { } Expect(k8sClient.Create(context.Background(), created)).Should(Succeed()) }) + + switchPool, err := vswpool.NewSwitchPool(100, "10m") + Expect(err).NotTo(HaveOccurred()) + + openAPI.On("DescribeVSwitchByID", mock.Anything, "vsw-not-exist").Return(nil, fmt.Errorf("not found")) + + It("should successfully reconcile the resource", func() { + controllerReconciler := &ReconcilePodNetworking{ + client: k8sClient, + aliyunClient: openAPI, + swPool: switchPool, + record: record.NewFakeRecorder(100), + } + + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + }) + It("Status Should Be Fail", func() { created := &networkv1beta1.PodNetworking{} Eventually(func(g Gomega) networkv1beta1.NetworkingStatus { - err := k8sClient.Get(context.Background(), key, created) + err := k8sClient.Get(context.Background(), typeNamespacedName, created) g.Expect(err).NotTo(HaveOccurred()) return created.Status.Status }, 5*time.Second, 500*time.Millisecond).Should(Equal(networkv1beta1.NetworkingStatusFail)) diff --git a/pkg/controller/pod-networking/predict.go b/pkg/controller/pod-networking/predict.go index 14980d65..f6b93a5e 100644 --- a/pkg/controller/pod-networking/predict.go +++ b/pkg/controller/pod-networking/predict.go @@ -17,9 +17,12 @@ limitations under the License. package podnetworking import ( - "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" + "github.com/samber/lo" + "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" + + "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" ) type predicateForPodnetwokringEvent struct { @@ -32,9 +35,18 @@ func (p *predicateForPodnetwokringEvent) Update(e event.UpdateEvent) bool { return false } - if newPodNetworking.Status.Status == "" { + switch newPodNetworking.Status.Status { + case "", v1beta1.NetworkingStatusFail: return true } - return false + return changed(newPodNetworking) +} + +func changed(pn *v1beta1.PodNetworking) bool { + expect := sets.New[string](pn.Spec.VSwitchOptions...) + got := sets.New[string](lo.Map([]v1beta1.VSwitch{}, func(item v1beta1.VSwitch, index int) string { + return item.ID + })...) + return expect.Equal(got) } diff --git a/pkg/controller/pod-networking/predict_test.go b/pkg/controller/pod-networking/predict_test.go new file mode 100644 index 00000000..e7fbfa12 --- /dev/null +++ b/pkg/controller/pod-networking/predict_test.go @@ -0,0 +1,47 @@ +package podnetworking + +import ( + "testing" + + "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" +) + +func Test_changed(t *testing.T) { + type args struct { + pn *v1beta1.PodNetworking + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "un sorted", + args: args{ + pn: &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + VSwitchOptions: []string{"foo", "bar"}, + }, + Status: v1beta1.PodNetworkingStatus{ + VSwitches: []v1beta1.VSwitch{ + { + Zone: "var", + }, + { + Zone: "foo", + }, + }, + }, + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := changed(tt.args.pn); got != tt.want { + t.Errorf("changed() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/controller/pod-networking/suite_test.go b/pkg/controller/pod-networking/suite_test.go index 94d5b4c5..488a5e27 100644 --- a/pkg/controller/pod-networking/suite_test.go +++ b/pkg/controller/pod-networking/suite_test.go @@ -1,37 +1,36 @@ -//go:build test_env - package podnetworking import ( - "context" + "fmt" "path/filepath" + "runtime" "testing" - "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" - networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" - register "github.com/AliyunContainerService/terway/pkg/controller" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" - "github.com/AliyunContainerService/terway/types/controlplane" + corev1 "k8s.io/api/core/v1" - "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + + networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" + "github.com/AliyunContainerService/terway/pkg/controller/mocks" ) var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment +var openAPI *mocks.Interface func TestAPIs(t *testing.T) { RegisterFailHandler(Fail) + openAPI = mocks.NewInterface(t) + RunSpecs(t, "Controller Suite") } @@ -42,50 +41,27 @@ var _ = BeforeSuite(func() { testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "apis", "crds")}, ErrorIfCRDPathMissing: true, + BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", + fmt.Sprintf("1.29.0-%s-%s", runtime.GOOS, runtime.GOARCH)), } - cfg, err := testEnv.Start() + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) + err = corev1.AddToScheme(scheme.Scheme) err = networkv1beta1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:scheme + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) - k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme.Scheme, - }) - Expect(err).ToNot(HaveOccurred()) - - vsw, err := vswitch.NewSwitchPool(1000, "100m") - Expect(err).ToNot(HaveOccurred()) - - fakeClient := &fake.OpenAPI{ - VSwitches: map[string]vpc.VSwitch{ - "vsw-1": { - VSwitchId: "vsw-1", - AvailableIpAddressCount: 100, - }, - }, - } - err = register.Controllers[controllerName].Creator(k8sManager, ®ister.ControllerCtx{ - Config: &controlplane.Config{}, - VSwitchPool: vsw, - AliyunClient: fakeClient, - DelegateClient: fakeClient, - }) - Expect(err).ToNot(HaveOccurred()) - - go func() { - defer GinkgoRecover() - err = k8sManager.Start(context.Background()) - Expect(err).ToNot(HaveOccurred(), "failed to run manager") - }() - -}, 5) +}) var _ = AfterSuite(func() { By("tearing down the test environment") diff --git a/pkg/controller/pod/pod_controller.go b/pkg/controller/pod/pod_controller.go index 95eccfb7..fe4867f7 100644 --- a/pkg/controller/pod/pod_controller.go +++ b/pkg/controller/pod/pod_controller.go @@ -28,8 +28,8 @@ import ( register "github.com/AliyunContainerService/terway/pkg/controller" "github.com/AliyunContainerService/terway/pkg/controller/common" eni_pool "github.com/AliyunContainerService/terway/pkg/controller/pool" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/utils" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/controlplane" "github.com/AliyunContainerService/terway/types/daemon" diff --git a/pkg/controller/pod/pod_controller_default.go b/pkg/controller/pod/pod_controller_default.go index 42167690..f9f6ddf2 100644 --- a/pkg/controller/pod/pod_controller_default.go +++ b/pkg/controller/pod/pod_controller_default.go @@ -8,7 +8,7 @@ import ( "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" "github.com/AliyunContainerService/terway/pkg/controller/common" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types/controlplane" ) diff --git a/pkg/controller/pod/pod_controller_test.go b/pkg/controller/pod/pod_controller_test.go index 4cfce4fb..1c2123de 100644 --- a/pkg/controller/pod/pod_controller_test.go +++ b/pkg/controller/pod/pod_controller_test.go @@ -9,7 +9,7 @@ import ( networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" "github.com/AliyunContainerService/terway/types" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/controller/pod/suite_test.go b/pkg/controller/pod/suite_test.go index d16f8ec7..00595224 100644 --- a/pkg/controller/pod/suite_test.go +++ b/pkg/controller/pod/suite_test.go @@ -10,13 +10,8 @@ import ( "path/filepath" "testing" - "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" - networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" - register "github.com/AliyunContainerService/terway/pkg/controller" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" - "github.com/AliyunContainerService/terway/types/controlplane" "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,6 +22,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" + networkv1beta1 "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" + register "github.com/AliyunContainerService/terway/pkg/controller" + "github.com/AliyunContainerService/terway/pkg/vswitch" + "github.com/AliyunContainerService/terway/types/controlplane" ) var cfg *rest.Config diff --git a/pkg/controller/pool/eni_mgr.go b/pkg/controller/pool/eni_mgr.go index 714bd49d..853650da 100644 --- a/pkg/controller/pool/eni_mgr.go +++ b/pkg/controller/pool/eni_mgr.go @@ -29,7 +29,7 @@ import ( "github.com/AliyunContainerService/terway/pkg/backoff" register "github.com/AliyunContainerService/terway/pkg/controller" "github.com/AliyunContainerService/terway/pkg/controller/common" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" diff --git a/pkg/controller/pool/eni_mgr_test.go b/pkg/controller/pool/eni_mgr_test.go index 8fdbb5f0..654257f1 100644 --- a/pkg/controller/pool/eni_mgr_test.go +++ b/pkg/controller/pool/eni_mgr_test.go @@ -7,7 +7,8 @@ import ( "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" "github.com/AliyunContainerService/terway/pkg/backoff" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" + "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/util/wait" diff --git a/pkg/controller/register.go b/pkg/controller/register.go index a396db9e..7514a1b8 100644 --- a/pkg/controller/register.go +++ b/pkg/controller/register.go @@ -14,11 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ +//go:generate mockery --name Interface --tags default_build + package register import ( "github.com/AliyunContainerService/terway/pkg/aliyun/client" - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types/controlplane" "sigs.k8s.io/controller-runtime/pkg/manager" diff --git a/pkg/factory/aliyun/aliyun.go b/pkg/factory/aliyun/aliyun.go index 176dd785..205ec22f 100644 --- a/pkg/factory/aliyun/aliyun.go +++ b/pkg/factory/aliyun/aliyun.go @@ -16,8 +16,8 @@ import ( "github.com/AliyunContainerService/terway/pkg/aliyun/eni" "github.com/AliyunContainerService/terway/pkg/aliyun/metadata" "github.com/AliyunContainerService/terway/pkg/backoff" - vswpool "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/factory" + vswpool "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/daemon" ) diff --git a/pkg/factory/aliyun/eflo.go b/pkg/factory/aliyun/eflo.go index bc6cabc3..88ba7f52 100644 --- a/pkg/factory/aliyun/eflo.go +++ b/pkg/factory/aliyun/eflo.go @@ -13,8 +13,8 @@ import ( "k8s.io/klog/v2" "github.com/AliyunContainerService/terway/pkg/aliyun/client" - vswpool "github.com/AliyunContainerService/terway/pkg/controller/vswitch" "github.com/AliyunContainerService/terway/pkg/factory" + vswpool "github.com/AliyunContainerService/terway/pkg/vswitch" "github.com/AliyunContainerService/terway/types" "github.com/AliyunContainerService/terway/types/daemon" ) diff --git a/pkg/controller/vswitch/vswitch.go b/pkg/vswitch/vswitch.go similarity index 100% rename from pkg/controller/vswitch/vswitch.go rename to pkg/vswitch/vswitch.go diff --git a/pkg/controller/vswitch/vswitch_test.go b/pkg/vswitch/vswitch_test.go similarity index 99% rename from pkg/controller/vswitch/vswitch_test.go rename to pkg/vswitch/vswitch_test.go index 6bc721d2..7d22c82d 100644 --- a/pkg/controller/vswitch/vswitch_test.go +++ b/pkg/vswitch/vswitch_test.go @@ -20,9 +20,10 @@ import ( "context" "testing" - "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" "github.com/stretchr/testify/assert" + + "github.com/AliyunContainerService/terway/pkg/aliyun/client/fake" ) func TestSwitchPool_GetOne(t *testing.T) { diff --git a/plugin/driver/utils/utils_linux_test.go b/plugin/driver/utils/utils_linux_test.go index 17232cce..8b9bb57d 100644 --- a/plugin/driver/utils/utils_linux_test.go +++ b/plugin/driver/utils/utils_linux_test.go @@ -7,14 +7,15 @@ import ( "runtime" "testing" - "github.com/AliyunContainerService/terway/pkg/tc" - terwayTypes "github.com/AliyunContainerService/terway/types" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/stretchr/testify/assert" "github.com/vishvananda/netlink" + + "github.com/AliyunContainerService/terway/pkg/tc" + terwayTypes "github.com/AliyunContainerService/terway/types" ) func TestCNI(t *testing.T) { @@ -182,7 +183,7 @@ var _ = Describe("Test TC filter", func() { eni, err := netlink.LinkByName(nicName) Expect(err).NotTo(HaveOccurred()) - Context("add new ip", func() { + By("add new ip", func() { err = EnsureVlanTag(eni, &terwayTypes.IPNetSet{ IPv4: &net.IPNet{ IP: net.ParseIP("192.168.1.1"), @@ -201,7 +202,7 @@ var _ = Describe("Test TC filter", func() { Expect(len(filters)).Should(Equal(2)) }) - Context("re-add same ip shoud succeed", func() { + By("re-add same ip shoud succeed", func() { err = EnsureVlanTag(eni, &terwayTypes.IPNetSet{ IPv4: &net.IPNet{ IP: net.ParseIP("192.168.1.1"), @@ -220,7 +221,7 @@ var _ = Describe("Test TC filter", func() { Expect(len(filters)).Should(Equal(2)) }) - Context("add new rule should success", func() { + By("add new rule should success", func() { err = EnsureVlanTag(eni, &terwayTypes.IPNetSet{ IPv4: &net.IPNet{ IP: net.ParseIP("192.168.1.2"), @@ -239,7 +240,7 @@ var _ = Describe("Test TC filter", func() { Expect(len(filters)).Should(Equal(4)) }) - Context("delete filter should clean up", func() { + By("delete filter should clean up", func() { err = DelFilter(eni, netlink.HANDLE_MIN_EGRESS, &terwayTypes.IPNetSet{ IPv4: &net.IPNet{ IP: net.ParseIP("192.168.1.2"), @@ -258,7 +259,7 @@ var _ = Describe("Test TC filter", func() { Expect(len(filters)).Should(Equal(2)) }) - Context("add same ip vid should be updated", func() { + By("add same ip vid should be updated", func() { err = EnsureVlanTag(eni, &terwayTypes.IPNetSet{ IPv4: &net.IPNet{ IP: net.ParseIP("192.168.1.1"), diff --git a/types/config.go b/types/config.go index ed45588f..a5688cef 100644 --- a/types/config.go +++ b/types/config.go @@ -1,7 +1,7 @@ package types import ( - "github.com/AliyunContainerService/terway/pkg/controller/vswitch" + "github.com/AliyunContainerService/terway/pkg/vswitch" ) type ENIConfig struct { diff --git a/types/controlplane/config.go b/types/controlplane/config.go index 67695fe2..a3787697 100644 --- a/types/controlplane/config.go +++ b/types/controlplane/config.go @@ -21,11 +21,12 @@ import ( "fmt" "os" - "github.com/AliyunContainerService/terway/pkg/aliyun/metadata" - "github.com/AliyunContainerService/terway/pkg/backoff" "github.com/go-playground/mold/v4/modifiers" "github.com/go-playground/validator/v10" "k8s.io/apimachinery/pkg/util/yaml" + + "github.com/AliyunContainerService/terway/pkg/aliyun/metadata" + "github.com/AliyunContainerService/terway/pkg/backoff" ) var (