diff --git a/.gitignore b/.gitignore index 7f552e91c2..b083920c15 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,6 @@ zz_generated.openapi.go #Tilt files. .tiltbuild + +# sshuttle +sshuttle.pid diff --git a/.golangci.yml b/.golangci.yml index 43505014ab..b434b4fe1e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -26,6 +26,9 @@ issues: - "G108: Profiling endpoint is automatically exposed on /debug/pprof" run: timeout: 6m + build-tags: + - e2e + skip-files: - "zz_generated.*\\.go$" - ".*_mock\\.go" diff --git a/Makefile b/Makefile index 1a76079abb..57c9e5ebe2 100644 --- a/Makefile +++ b/Makefile @@ -12,59 +12,73 @@ # See the License for the specific language governing permissions and # limitations under the License. -# If you update this file, please follow -# https://suva.sh/posts/well-documented-makefiles - -# Ensure Make is run with bash shell as some syntax below is bash-specific -SHELL:=/usr/bin/env bash - -.DEFAULT_GOAL:=help - -# Use GOPROXY environment variable if set -GOPROXY := $(shell go env GOPROXY) -ifeq ($(GOPROXY),) -GOPROXY := https://proxy.golang.org -endif -export GOPROXY +ROOT_DIR_RELATIVE := . -# Activate module mode, as we use go modules to manage dependencies -export GO111MODULE=on +include $(ROOT_DIR_RELATIVE)/common.mk -# This option is for running docker manifest command -export DOCKER_CLI_EXPERIMENTAL := enabled +# If you update this file, please follow +# https://suva.sh/posts/well-documented-makefiles # Directories. -REPO_ROOT := $(shell git rev-parse --show-toplevel) +ARTIFACTS ?= $(REPO_ROOT)/_artifacts TOOLS_DIR := hack/tools +TOOLS_DIR_DEPS := $(TOOLS_DIR)/go.sum $(TOOLS_DIR)/go.mod $(TOOLS_DIR)/Makefile TOOLS_BIN_DIR := $(TOOLS_DIR)/bin + BIN_DIR := bin +REPO_ROOT := $(shell git rev-parse --show-toplevel) +GH_REPO ?= kubernetes-sigs/cluster-api-provider-openstack +TEST_E2E_DIR := test/e2e + +# Files +E2E_DATA_DIR ?= $(REPO_ROOT)/test/e2e/data +E2E_CONF_PATH ?= $(E2E_DATA_DIR)/e2e_conf.yaml +KUBETEST_CONF_PATH ?= $(abspath $(E2E_DATA_DIR)/kubetest/conformance.yaml) +KUBETEST_FAST_CONF_PATH ?= $(abspath $(E2E_DATA_DIR)/kubetest/conformance-fast.yaml) # Binaries. -KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize -CLUSTERCTL := $(TOOLS_BIN_DIR)/clusterctl CONTROLLER_GEN := $(TOOLS_BIN_DIR)/controller-gen +CONVERSION_GEN := $(TOOLS_BIN_DIR)/conversion-gen +DEFAULTER_GEN := $(TOOLS_BIN_DIR)/defaulter-gen ENVSUBST := $(TOOLS_BIN_DIR)/envsubst +GINKGO := $(TOOLS_BIN_DIR)/ginkgo GOLANGCI_LINT := $(TOOLS_BIN_DIR)/golangci-lint +KIND := $(TOOLS_BIN_DIR)/kind +KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize MOCKGEN := $(TOOLS_BIN_DIR)/mockgen -CONVERSION_GEN := $(TOOLS_BIN_DIR)/conversion-gen -RELEASE_NOTES_BIN := bin/release-notes -RELEASE_NOTES := $(TOOLS_DIR)/$(RELEASE_NOTES_BIN) -GINKGO := $(TOOLS_BIN_DIR)/ginkgo +RELEASE_NOTES := $(TOOLS_BIN_DIR)/release-notes + +PATH := $(abspath $(TOOLS_BIN_DIR)):$(PATH) +DOCKER_CLI_EXPERIMENTAL=enabled +DOCKER_BUILDKIT=1 # Set --output-base for conversion-gen if we are not within GOPATH ifneq ($(abspath $(REPO_ROOT)),$(shell go env GOPATH)/src/sigs.k8s.io/cluster-api-provider-openstack) GEN_OUTPUT_BASE := --output-base=$(REPO_ROOT) endif -# Define Docker related variables. Releases should modify and double check these vars. -REGISTRY ?= gcr.io/k8s-staging-capi-openstack +# Release variables + STAGING_REGISTRY := gcr.io/k8s-staging-capi-openstack PROD_REGISTRY := us.gcr.io/k8s-artifacts-prod/capi-openstack -IMAGE_NAME ?= capi-openstack-controller -CONTROLLER_IMG ?= $(REGISTRY)/$(IMAGE_NAME) +REGISTRY ?= $(STAGING_REGISTRY) +RELEASE_TAG ?= $(shell git describe --abbrev=0 2>/dev/null) +PULL_BASE_REF ?= $(RELEASE_TAG) # PULL_BASE_REF will be provided by Prow +RELEASE_ALIAS_TAG ?= $(PULL_BASE_REF) +RELEASE_DIR := out + TAG ?= dev ARCH ?= amd64 -ALL_ARCH = amd64 arm arm64 ppc64le s390x +ALL_ARCH ?= amd64 arm arm64 ppc64le s390x + +# main controller +IMAGE_NAME ?= capi-openstack-controller +CONTROLLER_IMG ?= $(REGISTRY)/$(IMAGE_NAME) +CONTROLLER_ORIGINAL_IMG := gcr.io/k8s-staging-capi-openstack/capi-openstack-controller +CONTROLLER_NAME := capa-controller-manager +MANIFEST_FILE := infrastructure-components +CONFIG_DIR := config +NAMESPACE := capa-system # Allow overriding manifest generation destination directory MANIFEST_ROOT ?= config @@ -73,88 +87,55 @@ WEBHOOK_ROOT ?= $(MANIFEST_ROOT)/webhook RBAC_ROOT ?= $(MANIFEST_ROOT)/rbac # Allow overriding the imagePullPolicy -PULL_POLICY ?= IfNotPresent - -# Hosts running SELinux need :z added to volume mounts -SELINUX_ENABLED := $(shell cat /sys/fs/selinux/enforce 2> /dev/null || echo 0) - -ifeq ($(SELINUX_ENABLED),1) - DOCKER_VOL_OPTS?=:z -endif +PULL_POLICY ?= Always # Set build time variables including version details LDFLAGS := $(shell source ./hack/version.sh; version::ldflags) -## -------------------------------------- -## Help -## -------------------------------------- -help: ## Display this help - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ## -------------------------------------- -## Define targets for prow +## Testing ## -------------------------------------- +$(ARTIFACTS): + mkdir -p $@ -.PHONY: images -images: docker-build ## Build all images +.PHONY: test +test: ## Run tests + go test -v ./... -.PHONY: check -check: modules generate lint test verify +.PHONY: e2e-image +e2e-image: docker-pull-prerequisites + docker build -f Dockerfile --tag="gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:e2e" . -## -------------------------------------- -## Testing -## -------------------------------------- +E2E_ARGS ?= +CONFORMANCE_E2E_ARGS ?= -kubetest.config-file=$(KUBETEST_CONF_PATH) +CONFORMANCE_E2E_ARGS += $(E2E_ARGS) +CONFORMANCE_GINKGO_ARGS ?= -stream +CONFORMANCE_GINKGO_ARGS += $(GINKGO_ARGS) +.PHONY: test-conformance +test-conformance: $(GINKGO) $(KIND) $(KUSTOMIZE) e2e-image ## Run clusterctl based conformance test on workload cluster (requires Docker). + time $(GINKGO) -trace -progress -v -tags=e2e -focus="conformance" $(CONFORMANCE_GINKGO_ARGS) ./test/e2e/suites/conformance/... -- -config-path="$(E2E_CONF_PATH)" -artifacts-folder="$(ARTIFACTS)" --data-folder="$(E2E_DATA_DIR)" $(CONFORMANCE_E2E_ARGS) -.PHONY: test -test: generate lint ## Run tests - $(MAKE) test-go -.PHONY: test-go -test-go: ## Run golang tests - go test -v ./... +test-conformance-fast: ## Run clusterctl based conformance test on workload cluster (requires Docker) using a subset of the conformance suite in parallel. + $(MAKE) test-conformance CONFORMANCE_E2E_ARGS="-kubetest.config-file=$(KUBETEST_FAST_CONF_PATH) -kubetest.ginkgo-nodes=5 $(E2E_ARGS)" ## -------------------------------------- ## Binaries ## -------------------------------------- -$(GINKGO): $(TOOLS_DIR)/go.mod - cd $(TOOLS_DIR) && go build -tags=tools -o $(BIN_DIR)/ginkgo github.com/onsi/ginkgo/ginkgo .PHONY: binaries -binaries: manager ## Builds and installs all binaries - -.PHONY: manager -manager: ## Build manager binary. - go build -ldflags "$(LDFLAGS)" -o $(BIN_DIR)/manager . +binaries: managers ## Builds and installs all binaries -## -------------------------------------- -## Tooling Binaries -## -------------------------------------- - -$(CLUSTERCTL): ## Build clusterctl binary (we have to set some gitVersion, otherwise commands will fail) - cd $(TOOLS_DIR); go build -tags=tools -ldflags "-X 'sigs.k8s.io/cluster-api/version.gitVersion=v0.4.0-dirty'" -o $(BIN_DIR)/clusterctl sigs.k8s.io/cluster-api/cmd/clusterctl - -$(KUSTOMIZE): # Build kustomize from tools folder. - hack/ensure-kustomize.sh - -$(CONTROLLER_GEN): $(TOOLS_DIR)/go.mod # Build controller-gen from tools folder. - cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/controller-gen sigs.k8s.io/controller-tools/cmd/controller-gen - -$(ENVSUBST): $(TOOLS_DIR)/go.mod # Build envsubst from tools folder. - cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/envsubst github.com/a8m/envsubst/cmd/envsubst +.PHONY: managers +managers: + $(MAKE) manager-openstack-infrastructure -$(GOLANGCI_LINT): $(TOOLS_DIR)/go.mod # Build golangci-lint from tools folder. - cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint - -$(MOCKGEN): $(TOOLS_DIR)/go.mod # Build mockgen from tools folder. - cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/mockgen github.com/golang/mock/mockgen - -$(CONVERSION_GEN): $(TOOLS_DIR)/go.mod - cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/conversion-gen k8s.io/code-generator/cmd/conversion-gen - -$(RELEASE_NOTES) : $(TOOLS_DIR)/go.mod - cd $(TOOLS_DIR) && go build -tags tools -o $(BIN_DIR)/release-notes sigs.k8s.io/cluster-api/hack/tools/release +.PHONY: manager-openstack-infrastructure +manager-openstack-infrastructure: ## Build manager binary. + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "${LDFLAGS} -extldflags '-static'" -o $(BIN_DIR)/manager . ## -------------------------------------- ## Linting @@ -182,7 +163,9 @@ generate: ## Generate code $(MAKE) generate-manifests .PHONY: generate-go -generate-go: $(CONTROLLER_GEN) $(CONVERSION_GEN) $(MOCKGEN) ## Runs Go related generate targets +generate-go: $(MOCKGEN) + go generate ./... + $(MAKE) -B $(CONTROLLER_GEN) $(CONVERSION_GEN) $(DEFAULTER_GEN) $(CONTROLLER_GEN) \ paths=./api/... \ object:headerFile=./hack/boilerplate/boilerplate.generatego.txt @@ -191,7 +174,6 @@ generate-go: $(CONTROLLER_GEN) $(CONVERSION_GEN) $(MOCKGEN) ## Runs Go related g --input-dirs=./api/v1alpha3 \ --output-file-base=zz_generated.conversion $(GEN_OUTPUT_BASE) \ --go-header-file=./hack/boilerplate/boilerplate.generatego.txt - go generate ./... .PHONY: generate-manifests generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc. @@ -210,22 +192,20 @@ generate-manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc. ## Docker ## -------------------------------------- -.PHONY: docker-pull-prerequisites -docker-pull-prerequisites: - docker pull docker.io/docker/dockerfile:1.1-experimental - docker pull docker.io/library/golang:1.16.0 - docker pull gcr.io/distroless/static:latest - .PHONY: docker-build docker-build: docker-pull-prerequisites ## Build the docker image for controller-manager - DOCKER_BUILDKIT=1 docker build --build-arg goproxy=$(GOPROXY) --build-arg ARCH=$(ARCH) --build-arg LDFLAGS="$(LDFLAGS)" . -t $(CONTROLLER_IMG)-$(ARCH):$(TAG) - MANIFEST_IMG=$(CONTROLLER_IMG)-$(ARCH) MANIFEST_TAG=$(TAG) $(MAKE) set-manifest-image - $(MAKE) set-manifest-pull-policy + docker build --build-arg goproxy=$(GOPROXY) --build-arg ARCH=$(ARCH) --build-arg LDFLAGS="$(LDFLAGS)" . -t $(CONTROLLER_IMG)-$(ARCH):$(TAG) .PHONY: docker-push docker-push: ## Push the docker image docker push $(CONTROLLER_IMG)-$(ARCH):$(TAG) +.PHONY: docker-pull-prerequisites +docker-pull-prerequisites: + docker pull docker.io/docker/dockerfile:1.1-experimental + docker pull docker.io/library/golang:$(GOLANG_VERSION) + docker pull gcr.io/distroless/static:latest + ## -------------------------------------- ## Docker — All ARCH ## -------------------------------------- @@ -249,76 +229,130 @@ docker-push-manifest: ## Push the fat manifest docker image. docker manifest create --amend $(CONTROLLER_IMG):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(CONTROLLER_IMG)\-&:$(TAG)~g") @for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${CONTROLLER_IMG}:${TAG} ${CONTROLLER_IMG}-$${arch}:${TAG}; done docker manifest push --purge ${CONTROLLER_IMG}:${TAG} - MANIFEST_IMG=$(CONTROLLER_IMG) MANIFEST_TAG=$(TAG) $(MAKE) set-manifest-image - $(MAKE) set-manifest-pull-policy -.PHONY: set-manifest-image -set-manifest-image: - $(info Updating kustomize image patch file for manager resource) - sed -i'' -e 's@image: .*@image: '"${MANIFEST_IMG}:$(MANIFEST_TAG)"'@' ./config/default/manager_image_patch.yaml - - -.PHONY: set-manifest-pull-policy -set-manifest-pull-policy: - $(info Updating kustomize pull policy file for manager resource) - sed -i'' -e 's@imagePullPolicy: .*@imagePullPolicy: '"$(PULL_POLICY)"'@' ./config/default/manager_pull_policy.yaml +.PHONY: staging-manifests +staging-manifests: + $(MAKE) $(RELEASE_DIR)/$(MANIFEST_FILE).yaml PULL_POLICY=IfNotPresent TAG=$(RELEASE_ALIAS_TAG) ## -------------------------------------- ## Release ## -------------------------------------- -RELEASE_TAG := $(shell git describe --tags --abbrev=0 2>/dev/null) -RELEASE_DIR := out - $(RELEASE_DIR): - mkdir -p $(RELEASE_DIR)/ + mkdir -p $@ -.PHONY: release -release: clean-release ## Builds and push container images using the latest git tag for the commit. +.PHONY: list-staging-releases +list-staging-releases: ## List staging images for image promotion + @echo $(IMAGE_NAME): + $(MAKE) list-image RELEASE_TAG=$(RELEASE_TAG) IMAGE=$(IMAGE_NAME) + +list-image: + gcloud container images list-tags $(STAGING_REGISTRY)/$(IMAGE) --filter="tags=('$(RELEASE_TAG)')" --format=json + +.PHONY: check-release-tag +check-release-tag: @if [ -z "${RELEASE_TAG}" ]; then echo "RELEASE_TAG is not set"; exit 1; fi @if ! [ -z "$$(git status --porcelain)" ]; then echo "Your local git repository contains uncommitted changes, use git clean before proceeding."; exit 1; fi + +.PHONY: release +release: $(RELEASE_NOTES) clean-release check-release-tag $(RELEASE_DIR) ## Builds and push container images using the latest git tag for the commit. git checkout "${RELEASE_TAG}" - # Set the manifest image to the production bucket. - $(MAKE) set-manifest-image MANIFEST_IMG=$(PROD_REGISTRY)/$(IMAGE_NAME) MANIFEST_TAG=$(RELEASE_TAG) - $(MAKE) set-manifest-pull-policy PULL_POLICY=IfNotPresent + @if [ -z "${PREVIOUS_VERSION}" ]; then echo "PREVIOUS_VERSION is not set"; exit 1; fi + $(RELEASE_NOTES) --from $(PREVIOUS_VERSION) > $(RELEASE_DIR)/CHANGELOG.md + $(MAKE) release-notes $(MAKE) release-manifests + $(MAKE) release-templates .PHONY: release-manifests -release-manifests: $(RELEASE_DIR) $(KUSTOMIZE) ## Builds the manifests to publish with a release - $(KUSTOMIZE) build config/default > $(RELEASE_DIR)/infrastructure-components.yaml +release-manifests: + $(MAKE) $(RELEASE_DIR)/$(MANIFEST_FILE).yaml TAG=$(RELEASE_TAG) PULL_POLICY=IfNotPresent + # Add metadata to the release artifacts + cp metadata.yaml $(RELEASE_DIR)/metadata.yaml .PHONY: release-staging -release-staging: ## Builds and push container images to the staging bucket. - REGISTRY=$(STAGING_REGISTRY) $(MAKE) docker-build-all docker-push-all release-alias-tag +release-staging: ## Builds and push container images and manifests to the staging bucket. + $(MAKE) docker-build-all + $(MAKE) docker-push-all + $(MAKE) release-alias-tag + $(MAKE) staging-manifests + $(MAKE) upload-staging-artifacts + +.PHONY: upload-staging-artifacts +upload-staging-artifacts: ## Upload release artifacts to the staging bucket + gsutil cp $(RELEASE_DIR)/* gs://$(BUCKET)/components/$(RELEASE_ALIAS_TAG) -RELEASE_ALIAS_TAG=$(PULL_BASE_REF) +.PHONY: create-gh-release +create-gh-release:$(GH) ## Create release on Github + $(GH) release create $(VERSION) -d -F $(RELEASE_DIR)/CHANGELOG.md -t $(VERSION) -R $(GH_REPO) + +.PHONY: upload-gh-artifacts +upload-gh-artifacts: $(GH) ## Upload artifacts to Github release + $(GH) release upload $(VERSION) -R $(GH_REPO) --clobber $(RELEASE_DIR)/* .PHONY: release-alias-tag release-alias-tag: # Adds the tag to the last build tag. - gcloud container images add-tag $(CONTROLLER_IMG):$(TAG) $(CONTROLLER_IMG):$(RELEASE_ALIAS_TAG) + gcloud container images add-tag -q $(CONTROLLER_IMG):$(TAG) $(CONTROLLER_IMG):$(RELEASE_ALIAS_TAG) .PHONY: release-notes -release-notes: $(RELEASE_NOTES) +release-notes: $(RELEASE_NOTES) ## Generate release notes $(RELEASE_NOTES) $(ARGS) +.PHONY: release-templates +release-templates: $(RELEASE_DIR) ## Generate release templates + cp templates/cluster-template*.yaml $(RELEASE_DIR)/ + +IMAGE_PATCH_DIR := $(ARTIFACTS)/image-patch + +$(IMAGE_PATCH_DIR): $(ARTIFACTS) + mkdir -p $@ + +.PHONY: $(RELEASE_DIR)/$(MANIFEST_FILE).yaml +$(RELEASE_DIR)/$(MANIFEST_FILE).yaml: + $(MAKE) compiled-manifest \ + PROVIDER=$(MANIFEST_FILE) \ + OLD_IMG=$(CONTROLLER_ORIGINAL_IMG) \ + MANIFEST_IMG=$(CONTROLLER_IMG) \ + CONTROLLER_NAME=$(CONTROLLER_NAME) \ + PROVIDER_CONFIG_DIR=$(CONFIG_DIR) \ + NAMESPACE=$(NAMESPACE) + +.PHONY: compiled-manifest +compiled-manifest: $(RELEASE_DIR) $(KUSTOMIZE) + $(MAKE) image-patch-source-manifest + $(MAKE) image-patch-pull-policy + $(KUSTOMIZE) build $(IMAGE_PATCH_DIR)/$(PROVIDER) > $(RELEASE_DIR)/$(PROVIDER).yaml + +.PHONY: image-patch-source-manifest +image-patch-source-manifest: $(IMAGE_PATCH_DIR) $(KUSTOMIZE) + mkdir -p $(IMAGE_PATCH_DIR)/$(PROVIDER) + $(KUSTOMIZE) build $(PROVIDER_CONFIG_DIR) > $(IMAGE_PATCH_DIR)/$(PROVIDER)/source-manifest.yaml + +.PHONY: image-patch-pull-policy +image-patch-pull-policy: $(IMAGE_PATCH_DIR) $(GOJQ) + mkdir -p $(IMAGE_PATCH_DIR)/$(PROVIDER) + echo Setting imagePullPolicy to $(PULL_POLICY) + $(GOJQ) --yaml-input --yaml-output '.[0].value="$(PULL_POLICY)"' "hack/image-patch/pull-policy-patch.yaml" > $(IMAGE_PATCH_DIR)/$(PROVIDER)/pull-policy-patch.yaml + + ## -------------------------------------- ## Cleanup / Verification ## -------------------------------------- .PHONY: clean clean: ## Remove all generated files + $(MAKE) -C hack/tools clean $(MAKE) clean-bin $(MAKE) clean-temporary .PHONY: clean-bin clean-bin: ## Remove all generated binaries rm -rf bin - rm -rf hack/tools/bin .PHONY: clean-temporary clean-temporary: ## Remove all temporary files and folders rm -f minikube.kubeconfig rm -f kubeconfig + rm -rf _artifacts .PHONY: clean-release clean-release: ## Remove the release folder @@ -343,3 +377,7 @@ verify-gen: generate git diff; \ echo "generated files are out of date, run make generate"; exit 1; \ fi + +.PHONY: compile-e2e +compile-e2e: ## Test e2e compilation + go test -c -o /dev/null -tags=e2e ./test/e2e/suites/conformance diff --git a/common.mk b/common.mk new file mode 100644 index 0000000000..44211768a7 --- /dev/null +++ b/common.mk @@ -0,0 +1,57 @@ +# Copyright 2020 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. + +include $(ROOT_DIR_RELATIVE)/versions.mk + +# Ensure Make is run with bash shell as some syntax below is bash-specific +SHELL:=bash +.ONESHELL: +.EXPORT_ALL_VARIABLES: +.SHELLFLAGS := -eu -o pipefail -c +.DELETE_ON_ERROR: +MAKEFLAGS += --no-builtin-rules + +TOOLS_DIR := $(ROOT_DIR_RELATIVE)/hack/tools +TOOLS_DIR_DEPS := $(TOOLS_DIR)/go.sum $(TOOLS_DIR)/go.mod $(TOOLS_DIR)/Makefile +TOOLS_BIN_DIR := $(TOOLS_DIR)/bin +UID := $(shell id -u) +GID := $(shell id -g) + +rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) + +# Hosts running SELinux need :z added to volume mounts +SELINUX_ENABLED := $(shell cat /sys/fs/selinux/enforce 2> /dev/null || echo 0) + +ifeq ($(SELINUX_ENABLED),1) + DOCKER_VOL_OPTS?=:z +endif + +.DEFAULT_GOAL:=help + +# Use GOPROXY environment variable if set +GOPROXY := $(shell go env GOPROXY) +ifeq ($(GOPROXY),) +GOPROXY := https://proxy.golang.org +endif +export GOPROXY + +$(TOOLS_BIN_DIR)/%: $(TOOLS_DIR_DEPS) + make -C $(TOOLS_DIR) $(subst $(TOOLS_DIR)/,,$@) + +## -------------------------------------- +## Help +## -------------------------------------- + +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) diff --git a/config/default/manager_pull_policy.yaml b/config/default/manager_pull_policy.yaml index cd7ae12c01..74a0879c60 100644 --- a/config/default/manager_pull_policy.yaml +++ b/config/default/manager_pull_policy.yaml @@ -8,4 +8,4 @@ spec: spec: containers: - name: manager - imagePullPolicy: IfNotPresent + imagePullPolicy: Always diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 276594d082..b05ab3362c 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -22,7 +22,9 @@ spec: args: - "--leader-elect" - "--metrics-bind-addr=127.0.0.1:8080" + - "--v=2" image: controller:latest + imagePullPolicy: Always name: manager ports: - containerPort: 9440 diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go index 7cd28505e7..a201b7cd78 100644 --- a/controllers/openstackcluster_controller.go +++ b/controllers/openstackcluster_controller.go @@ -32,6 +32,7 @@ import ( "k8s.io/client-go/tools/record" clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4" "sigs.k8s.io/cluster-api/util" + "sigs.k8s.io/cluster-api/util/annotations" "sigs.k8s.io/cluster-api/util/patch" "sigs.k8s.io/cluster-api/util/predicates" ctrl "sigs.k8s.io/controller-runtime" @@ -87,7 +88,7 @@ func (r *OpenStackClusterReconciler) Reconcile(ctx context.Context, req ctrl.Req return reconcile.Result{}, nil } - if util.IsPaused(cluster, openStackCluster) { + if annotations.IsPaused(cluster, openStackCluster) { log.Info("OpenStackCluster or linked Cluster is marked as paused. Won't reconcile") return reconcile.Result{}, nil } diff --git a/controllers/openstackmachine_controller.go b/controllers/openstackmachine_controller.go index ee17da1655..4b9a913f5a 100644 --- a/controllers/openstackmachine_controller.go +++ b/controllers/openstackmachine_controller.go @@ -35,6 +35,7 @@ import ( clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4" capierrors "sigs.k8s.io/cluster-api/errors" "sigs.k8s.io/cluster-api/util" + "sigs.k8s.io/cluster-api/util/annotations" "sigs.k8s.io/cluster-api/util/patch" "sigs.k8s.io/cluster-api/util/predicates" ctrl "sigs.k8s.io/controller-runtime" @@ -103,7 +104,7 @@ func (r *OpenStackMachineReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, nil } - if util.IsPaused(cluster, openStackMachine) { + if annotations.IsPaused(cluster, openStackMachine) { log.Info("OpenStackMachine or linked Cluster is marked as paused. Won't reconcile") return ctrl.Result{}, nil } diff --git a/go.mod b/go.mod index c48809c1ee..830756add5 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,14 @@ require ( github.com/onsi/gomega v1.10.5 github.com/pkg/errors v0.9.1 github.com/spf13/pflag v1.0.5 - gopkg.in/yaml.v2 v2.3.0 + golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 + gopkg.in/ini.v1 v1.62.0 k8s.io/api v0.21.0-beta.0 k8s.io/apimachinery v0.21.0-beta.0 k8s.io/client-go v0.21.0-beta.0 k8s.io/klog/v2 v2.5.0 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 - sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c + sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4 sigs.k8s.io/controller-runtime v0.8.2-0.20210302195120-85527dfb5348 + sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 977bacc75b..04cc3e0ded 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,7 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -51,6 +52,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alessio/shellescape v1.2.2 h1:8LnL+ncxhWT2TR00dfJRT25JWWrhkMZXneHVWnetDZg= github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -116,6 +118,7 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a h1:pf3CyiWgjOLL7cjFos89AEOPCWSOoQt7tgbEk/SvBAg= github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -133,6 +136,7 @@ github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.1.0 h1:B0aXl1o/1cP8NbviYiBMkcHBtUjIJ1/Ccg6b+SwCLQg= github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= @@ -225,7 +229,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -254,6 +260,7 @@ github.com/gophercloud/gophercloud v0.15.0 h1:jQeAWj0s1p83+TrUXhJhEOK4oe2g6YcBcF github.com/gophercloud/gophercloud v0.15.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM= github.com/gophercloud/utils v0.0.0-20201203161420-f41c1768a042 h1:R/+WaNsfMEc3WAljyhQVkBJ9UsyBYxbOEqYCMUx4GiM= github.com/gophercloud/utils v0.0.0-20201203161420-f41c1768a042/go.mod h1:ehWUbLQJPqS0Ep+CxeD559hsm9pthPXadJNKwZkp43w= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -289,6 +296,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -314,6 +322,7 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -344,6 +353,7 @@ github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H7 github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -353,6 +363,7 @@ github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwm github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -370,6 +381,7 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= @@ -430,6 +442,7 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -489,17 +502,22 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -507,6 +525,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -521,6 +540,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -846,6 +866,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -913,10 +935,11 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c h1:Fva2ZI/os4dotzdD+zk+Rovv3A01JovSMDgvGfUc7nE= -sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c/go.mod h1:pww0lCxSkEXcDzkKYikhJ8k9MuFvLZAmLY6rFokvaZk= +sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4 h1:HiLm4yLlJad40oOZdMASQgXKNQ9LE5GkQ5qK0pBRX+4= +sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4/go.mod h1:pww0lCxSkEXcDzkKYikhJ8k9MuFvLZAmLY6rFokvaZk= sigs.k8s.io/controller-runtime v0.8.2-0.20210302195120-85527dfb5348 h1:9iK3tArPJp/PYbqUjzpjZJ94KGGOHhvloa4N0RzeZi8= sigs.k8s.io/controller-runtime v0.8.2-0.20210302195120-85527dfb5348/go.mod h1:WSqdxdrtK8mVoszWTAw0Jg3zfyHwvT8nn3B5tA2Hkms= +sigs.k8s.io/kind v0.9.0 h1:SoDlXq6pEc7dGagHULNRCCBYrLH6xOi7lqXTRXeAlg4= sigs.k8s.io/kind v0.9.0/go.mod h1:cxKQWwmbtRDzQ+RNKnR6gZG6fjbeTtItp5cGf+ww+1Y= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= diff --git a/hack/ci/.gitignore b/hack/ci/.gitignore index 40f662fb90..fbfc944419 100644 --- a/hack/ci/.gitignore +++ b/hack/ci/.gitignore @@ -1 +1 @@ -e2e-conformance-gcp-cloud-init.yaml \ No newline at end of file +devstack-cloud-init.yaml \ No newline at end of file diff --git a/hack/ci/e2e-conformance-gcp-cloud-init.yaml.tpl b/hack/ci/devstack-cloud-init.yaml.tpl similarity index 93% rename from hack/ci/e2e-conformance-gcp-cloud-init.yaml.tpl rename to hack/ci/devstack-cloud-init.yaml.tpl index efe09995fd..6131ae0cef 100644 --- a/hack/ci/e2e-conformance-gcp-cloud-init.yaml.tpl +++ b/hack/ci/devstack-cloud-init.yaml.tpl @@ -66,16 +66,19 @@ write_files: ENABLED_SERVICES+=,octavia,o-api,o-cw,o-hm,o-hk,o-da # Horizon (enable for manual tests) - #ENABLED_SERVICES+=,horizon + # ENABLED_SERVICES+=,horizon # Cinder ENABLED_SERVICES+=,c-sch,c-api,c-vol + # Additional services + ENABLED_SERVICES+=${OPENSTACK_ADDITIONAL_SERVICES} + LIBVIRT_TYPE=kvm # Don't download default images, just our test images DOWNLOAD_DEFAULT_IMAGES=False - IMAGE_URLS="https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.3.0/ubuntu-1910-kube-v1.17.3.qcow2," + IMAGE_URLS="https://github.com/sbueringer/image-builder/releases/download/v1.18.15-01/ubuntu-2004-kube-v1.18.15.qcow2," IMAGE_URLS+="http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" EOF diff --git a/hack/ci/e2e-conformance-gcp-prepare.sh b/hack/ci/devstack-on-gce-project-install.sh similarity index 92% rename from hack/ci/e2e-conformance-gcp-prepare.sh rename to hack/ci/devstack-on-gce-project-install.sh index 2fb9a4920b..724133e289 100755 --- a/hack/ci/e2e-conformance-gcp-prepare.sh +++ b/hack/ci/devstack-on-gce-project-install.sh @@ -18,7 +18,11 @@ set -o errexit -o nounset -o pipefail -CLUSTER_NAME=${CLUSTER_NAME:-"capi-quickstart"} +REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../ +cd "${REPO_ROOT}" || exit 1 +REPO_ROOT_ABSOLUTE=$(pwd) + +CLUSTER_NAME=${CLUSTER_NAME:-"capo-e2e"} GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS:-""} GCP_PROJECT=${GCP_PROJECT:-""} GCP_REGION=${GCP_REGION:-"us-east4"} @@ -27,6 +31,7 @@ GCP_MACHINE_MIN_CPU_PLATFORM=${GCP_MACHINE_MIN_CPU_PLATFORM:-"Intel Cascade Lake GCP_MACHINE_TYPE=${GCP_MACHINE_TYPE:-"n2-standard-16"} GCP_NETWORK_NAME=${GCP_NETWORK_NAME:-"${CLUSTER_NAME}-mynetwork"} OPENSTACK_RELEASE=${OPENSTACK_RELEASE:-"victoria"} +OPENSTACK_ADDITIONAL_SERVICES=${OPENSTACK_ADDITIONAL_SERVICES:-""} echo "Using: GCP_PROJECT: ${GCP_PROJECT} GCP_REGION: ${GCP_REGION} GCP_NETWORK_NAME: ${GCP_NETWORK_NAME}" @@ -110,9 +115,10 @@ main() { if ! gcloud compute instances describe openstack --project "${GCP_PROJECT}" --zone "${GCP_ZONE}" > /dev/null; then - < ./hack/ci/e2e-conformance-gcp-cloud-init.yaml.tpl \ - sed "s|\${OPENSTACK_RELEASE}|${OPENSTACK_RELEASE}|" \ - > ./hack/ci/e2e-conformance-gcp-cloud-init.yaml + < ./hack/ci/devstack-cloud-init.yaml.tpl \ + sed "s|\${OPENSTACK_RELEASE}|${OPENSTACK_RELEASE}|" | \ + sed "s|\${OPENSTACK_ADDITIONAL_SERVICES}|${OPENSTACK_ADDITIONAL_SERVICES}|" \ + > ./hack/ci/devstack-cloud-init.yaml gcloud compute instances create openstack \ --project "${GCP_PROJECT}" \ @@ -125,7 +131,7 @@ main() { --min-cpu-platform "${GCP_MACHINE_MIN_CPU_PLATFORM}" \ --machine-type "${GCP_MACHINE_TYPE}" \ --network-interface=network="${CLUSTER_NAME}-mynetwork,subnet=${CLUSTER_NAME}-mynetwork,aliases=/24" \ - --metadata-from-file user-data=./hack/ci/e2e-conformance-gcp-cloud-init.yaml + --metadata-from-file user-data=./hack/ci/devstack-cloud-init.yaml fi # Install some local deps we later need in the meantime (we have to wait for cloud init anyway) @@ -138,6 +144,7 @@ main() { git clone https://github.com/sshuttle/sshuttle.git cd sshuttle pip3 install . + cd "${REPO_ROOT_ABSOLUTE}" || exit 1 fi if ! command -v openstack; then @@ -188,7 +195,7 @@ main() { openstack flavor delete m1.tiny openstack flavor create --ram 512 --disk 1 --vcpus 1 --public --id 1 m1.tiny --property hw_rng:allowed='True' openstack flavor delete m1.small - openstack flavor create --ram 6144 --disk 10 --vcpus 2 --public --id 2 m1.small --property hw_rng:allowed='True' + openstack flavor create --ram 4192 --disk 10 --vcpus 2 --public --id 2 m1.small --property hw_rng:allowed='True' openstack flavor delete m1.medium openstack flavor create --ram 6144 --disk 10 --vcpus 4 --public --id 3 m1.medium --property hw_rng:allowed='True' @@ -196,7 +203,7 @@ main() { export OS_USERNAME=demo export OS_PROJECT_NAME=demo - cat << EOF > /tmp/clouds.yaml + cat << EOF > "${REPO_ROOT_ABSOLUTE}/clouds.yaml" clouds: ${CLUSTER_NAME}: auth: @@ -209,7 +216,8 @@ clouds: verify: false region_name: RegionOne EOF - cat /tmp/clouds.yaml + echo "${REPO_ROOT_ABSOLUTE}/clouds.yaml:" + cat "${REPO_ROOT_ABSOLUTE}/clouds.yaml" } main "$@" diff --git a/hack/ci/e2e-conformance.sh b/hack/ci/e2e-conformance.sh deleted file mode 100755 index b8172a224a..0000000000 --- a/hack/ci/e2e-conformance.sh +++ /dev/null @@ -1,584 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2019 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. - -# hack script for running a cluster-api-provider-openstack e2e - -set -o errexit -o nounset -o pipefail - -OPENSTACK_CLOUD=${OPENSTACK_CLOUD:-"capi-quickstart"} -OPENSTACK_CLOUD_YAML_FILE=${OPENSTACK_CLOUD_YAML_FILE:-"/tmp/clouds.yaml"} -IMAGE_URL="https://github.com/kubernetes-sigs/cluster-api-provider-openstack/releases/download/v0.3.0/ubuntu-1910-kube-v1.17.3.qcow2" -CIRROS_URL="http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" -OPENSTACK_IMAGE_NAME=${OPENSTACK_IMAGE_NAME:-"ubuntu-1910-kube-v1.17.3"} -OPENSTACK_BASTION_IMAGE_NAME=${OPENSTACK_BASTION_IMAGE_NAME:-"cirros-0.5.1-x86_64-disk"} -OPENSTACK_FAILURE_DOMAIN=${OPENSTACK_FAILURE_DOMAIN:-"nova"} -OPENSTACK_DNS_NAMESERVERS=${OPENSTACK_DNS_NAMESERVERS:-"192.168.200.1"} -OPENSTACK_NODE_MACHINE_FLAVOR=${OPENSTACK_NODE_MACHINE_FLAVOR:-"m1.small"} -WORKER_MACHINE_COUNT=${WORKER_MACHINE_COUNT:-"4"} -OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR=${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR:-"m1.medium"} -CONTROL_PLANE_MACHINE_COUNT=${CONTROL_PLANE_MACHINE_COUNT:-"1"} -OPENSTACK_BASTION_MACHINE_FLAVOR=${OPENSTACK_BASTION_MACHINE_FLAVOR:-"m1.tiny"} -OPENSTACK_CLUSTER_TEMPLATE=${OPENSTACK_CLUSTER_TEMPLATE:-"./templates/cluster-template.yaml"} -CLUSTER_NAME=${CLUSTER_NAME:-"capi-quickstart"} -OPENSTACK_SSH_KEY_NAME=${OPENSTACK_SSH_KEY_NAME:-"${CLUSTER_NAME}-key"} -KUBERNETES_VERSION=${KUBERNETES_VERSION:-"v1.20.4"} -USE_CI_ARTIFACTS=${USE_CI_ARTIFACTS:-"true"} -IMAGE_REPOSITORY=${IMAGE_REPOSITORY:-"k8s.gcr.io"} - -ARTIFACTS="${ARTIFACTS:-${PWD}/_artifacts}" -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" - -LOGS_DEVSTACK_DUMPED=false -LOGS_MGMT_DUMPED=false -LOGS_CAPO_DUMPED=false - -dump_devstack_logs() { - set -x - - if [[ "${LOGS_DEVSTACK_DUMPED}" == "true" ]]; - then - echo "mgmt logs already dumped" - return 0 - fi - LOGS_DEVSTACK_DUMPED=true - - echo "Dump logs" - dir="${ARTIFACTS}/logs/devstack" - mkdir -p "${dir}" - - # e.g.: http://10.150.0.2/identity => 10.150.0.2 - DEVSTACK_IP=$(echo "$CAPO_AUTH_URL" | awk -F[/:] '{print $4}') - scp -i ~/.ssh/google_compute_engine \ - -o "StrictHostKeyChecking no" -o "UserKnownHostsFile=/dev/null" -o "IdentitiesOnly=yes" \ - -r "root@${DEVSTACK_IP}:/var/log/cloud-init.log" "root@${DEVSTACK_IP}:/var/log/cloud-init-output.log" \ - "${dir}" || true -} - -dump_kind_logs() { - set -x - - if [[ "${LOGS_MGMT_DUMPED}" == "true" ]]; - then - echo "mgmt logs already dumped" - return 0 - fi - LOGS_MGMT_DUMPED=true - - iptables -t nat -L --line-numbers || true - - echo "Dump logs" - mkdir -p "${ARTIFACTS}/logs/mgmt" - - echo "=== versions ===" - echo "kind : $(kind version)" || true - echo "mgmt cluster:" - kubectl version || true - echo "" - - # dump all the info from the CAPI related CRDs - kubectl get clusters,openstackclusters,machines,openstackmachines,kubeadmconfigs,machinedeployments,openstackmachinetemplates,kubeadmconfigtemplates,machinesets --all-namespaces -o yaml > "${ARTIFACTS}/logs/mgmt/capo.txt" || true - - # dump images info - { echo "=== images in docker using docker images ==="; docker images;} >> "${ARTIFACTS}/logs/mgmt/images.txt" - echo "=== images in mgmt cluster using containerd CLI ===" >> "${ARTIFACTS}/logs/mgmt/images.txt" - docker exec clusterapi-control-plane ctr -n k8s.io images list >> "${ARTIFACTS}/logs/mgmt/images.txt" || true - echo "=== images in mgmt cluster using kubectl CLI" >> "${ARTIFACTS}/logs/mgmt/images.txt" - (kubectl get pods --all-namespaces -o json \ - | jq --raw-output '.items[].spec.containers[].image' | sort) >> "${ARTIFACTS}/logs/mgmt/images.txt" || true - - # dump cluster info for mgmt - kubectl cluster-info dump > "${ARTIFACTS}/logs/mgmt/cluster.txt" || true - kubectl get secrets -o yaml -A > "${ARTIFACTS}/logs/mgmt/cluster-secrets.txt" || true - - # export all logs from kind - kind export logs --name="clusterapi" "${ARTIFACTS}/logs/mgmt" || true - set +x -} - -dump_workload_logs() { - set -x - - if [[ "${LOGS_CAPO_DUMPED}" == "true" ]]; - then - echo "workload logs already dumped" - return 0 - fi - LOGS_CAPO_DUMPED=true - - echo "Dump logs" - mkdir -p "${ARTIFACTS}/logs/workload" - - echo "=== versions ===" - echo "workload cluster:" - kubectl --kubeconfig="${PWD}/kubeconfig" version || true - echo "" - - # dump images info - echo "=== images in workload cluster using kubectl CLI ===" >> "${ARTIFACTS}/logs/workload/images.txt" - (kubectl --kubeconfig="${PWD}"/kubeconfig get pods --all-namespaces -o json \ - | jq --raw-output '.items[].spec.containers[].image' | sort) >> "${ARTIFACTS}/logs/workload/images.txt" || true - - # dump cluster info for workload - kubectl --kubeconfig="${PWD}/kubeconfig" cluster-info dump >> "${ARTIFACTS}/logs/workload/cluster.txt" || true - kubectl --kubeconfig="${PWD}/kubeconfig" get secrets -o yaml -A > "${ARTIFACTS}/logs/workload/cluster-secrets.txt" || true - - # dump OpenStack info - echo "=== OpenStack compute images list ===" >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - openstack image list >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - echo "=== OpenStack compute instances list ===" >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - openstack server list >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - echo "=== OpenStack compute instances show ===" >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - openstack server list -f value -c Name | xargs -I% openstack server show % >> "${ARTIFACTS}/logs/workload/openstack.txt" || true - - jump_node_name=$(openstack server list -f value -c Name | grep "${CLUSTER_NAME}-bastion" | head -n 1) - jump_node=$(openstack server show "${jump_node_name}" -f value -c addresses | awk '{print $2}') - ssh_config="${ARTIFACTS}/ssh_config" - cat > "${ssh_config}" < "${dir}/openstack-console.log" || true - node=$(openstack port show "${node}" -f json -c fixed_ips | jq '.fixed_ips[0].ip_address' -r) - - ssh -F "${ssh_config}" "capi@${node}" "sudo chmod -R a+r /var/log" || true - scp -F "${ssh_config}" -r \ - "capi@${node}:/var/log/cloud-init.log" "capi@${node}:/var/log/cloud-init-output.log" \ - "capi@${node}:/var/log/pods" "capi@${node}:/var/log/containers" \ - "${dir}" || true - - ssh -F "${ssh_config}" "capi@${node}" "sudo journalctl --output=short-precise -k -b all" > "${dir}/kernel.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo journalctl --output=short-precise" > "${dir}/systemd.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo crictl version && sudo crictl info" > "${dir}/containerd.txt" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo journalctl --no-pager -u cloud-final" > "${dir}/cloud-final.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo journalctl --no-pager -u kubelet.service" > "${dir}/kubelet.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo journalctl --no-pager -u containerd.service" > "${dir}/containerd.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo top -b -n 1" > "${dir}/top.txt" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo crictl ps" > "${dir}/crictl-ps.log" || true - ssh -F "${ssh_config}" "capi@${node}" "sudo crictl pods" > "${dir}/crictl-pods.log" || true - done - set +x -} - -function dump_logs() { - dump_devstack_logs - dump_kind_logs - dump_workload_logs -} - -create_key_pair() { - echo "Create and upload key pair" - - if [[ -f /tmp/${OPENSTACK_SSH_KEY_NAME}.pem ]] && [[ -f /tmp/${OPENSTACK_SSH_KEY_NAME}.pem.pub ]] - then - echo "Skip generating key pair, it already exists" - else - ssh-keygen -t rsa -f "/tmp/${OPENSTACK_SSH_KEY_NAME}.pem" -N "" - chmod 0400 "/tmp/${OPENSTACK_SSH_KEY_NAME}.pem" - fi - OPENSTACK_SSH_KEY_PUBLIC=$(cat "/tmp/${OPENSTACK_SSH_KEY_NAME}.pem.pub") - - if ! openstack keypair show "${OPENSTACK_SSH_KEY_NAME}"; - then - openstack keypair create --public-key "/tmp/${OPENSTACK_SSH_KEY_NAME}.pem.pub" "${OPENSTACK_SSH_KEY_NAME}" - fi -} - -upload_image(){ - IMAGE_NAME=$1 - IMAGE_URL=$2 - - echo "Upload image" - - # Remove old image if we don't want to reuse it - if [[ "${REUSE_OLD_IMAGES:-true}" == "false" ]]; then - image_id=$(openstack image list --name="${IMAGE_NAME}" -f value -c ID) - if [[ -n "$image_id" ]]; then - echo "Deleting old image ${IMAGE_NAME} with id: ${image_id}" - openstack image delete "${image_id}" - fi - fi - - image=$(openstack image list --name="${IMAGE_NAME}" -f value -c Name) - if [[ -n "$image" ]]; then - echo "Image ""${IMAGE_NAME}"" already exists" - return - fi - - tmpfile=/tmp/"${IMAGE_NAME}" - if [ ! -f "${tmpfile}" ]; - then - echo "Download image ${IMAGE_NAME} from IMAGE_URL" - wget -q -c "IMAGE_URL" -O "${tmpfile}" - fi - - echo "Uploading image ${IMAGE_NAME}" - openstack image create --disk-format qcow2 --private --container-format bare --file "${tmpfile}" "${IMAGE_NAME}" -} - -install_prereqs() { - if ! command -v jq; - then - apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y jq - fi - - GO111MODULE=on go get github.com/mikefarah/yq/v2 - go get -u github.com/go-bindata/go-bindata/... -} - -# build kubernetes / node image, e2e binaries -build() { - # possibly enable bazel build caching before building kubernetes - if [[ "${BAZEL_REMOTE_CACHE_ENABLED:-false}" == "true" ]]; then - create_bazel_cache_rcs.sh || true - fi - - if [[ ! -d "$(go env GOPATH)/src/k8s.io/kubernetes" ]]; then - mkdir -p "$(go env GOPATH)/src/k8s.io" - cd "$(go env GOPATH)/src/k8s.io" - - git clone https://github.com/kubernetes/kubernetes.git - cd kubernetes - fi - - pushd "$(go env GOPATH)/src/k8s.io/kubernetes" - echo "Checking out Kubernetes version: ${KUBERNETES_VERSION}" - git checkout -b "${KUBERNETES_VERSION}" "refs/tags/${KUBERNETES_VERSION}" - - # cleanup old _output/bin folder - rm -rf "${PWD}/_output/bin" - - # make sure we have e2e requirements - make WHAT="test/e2e/e2e.test vendor/github.com/onsi/ginkgo/ginkgo cmd/kubectl" - - # ensure the e2e script will find our binaries ... - PATH="$(dirname "$(find "${PWD}/_output/bin/" -name kubectl -type f)"):${PATH}" - export PATH - - # attempt to release some memory after building - sync || true - sh -c "echo 1 > /proc/sys/vm/drop_caches" || true - - popd - - cd "${REPO_ROOT}" - echo "Build Docker Images" - make modules hack/tools/bin/clusterctl hack/tools/bin/kustomize hack/tools/bin/envsubst docker-build -} - -# CAPI/CAPO versions -# See: https://console.cloud.google.com/storage/browser/artifacts.k8s-staging-cluster-api.appspot.com/components?project=k8s-staging-cluster-api -E2E_CAPI_DOWNLOAD_VERSION=nightly_master_20210305 -E2E_CAPI_VERSION=0.4.0 -E2E_CAPO_VERSION=0.4.0 - -# up a cluster with kind -create_cluster() { - - cd "${REPO_ROOT}" - - # Create local repository to use local OpenStack provider and nightly CAPI - mkdir -p ./out - < ./hack/ci/e2e-conformance/clusterctl.yaml.tpl \ - sed "s|\${PWD}|${PWD}|" | \ - sed "s|\${E2E_CAPO_VERSION}|${E2E_CAPO_VERSION}|" | \ - sed "s|\${E2E_CAPI_VERSION}|${E2E_CAPI_VERSION}|" \ - > ./out/clusterctl.yaml - - mkdir -p ./out/infrastructure-openstack/${E2E_CAPO_VERSION} - MANIFEST_IMG=gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64 MANIFEST_TAG=dev make set-manifest-image - ./hack/tools/bin/kustomize build config/default > ./out/infrastructure-openstack/${E2E_CAPO_VERSION}/infrastructure-components.yaml - cp ./hack/ci/e2e-conformance/metadata.yaml ./out/infrastructure-openstack/${E2E_CAPO_VERSION}/metadata.yaml - - mkdir -p ./out/cluster-api/v${E2E_CAPI_VERSION} - wget https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/${E2E_CAPI_DOWNLOAD_VERSION}/core-components.yaml -O ./out/cluster-api/v${E2E_CAPI_VERSION}/core-components.yaml - cp ./hack/ci/e2e-conformance/metadata.yaml ./out/cluster-api/v${E2E_CAPI_VERSION}/metadata.yaml - - mkdir -p ./out/bootstrap-kubeadm/v${E2E_CAPI_VERSION} - wget https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/${E2E_CAPI_DOWNLOAD_VERSION}/bootstrap-components.yaml -O ./out/bootstrap-kubeadm/v${E2E_CAPI_VERSION}/bootstrap-components.yaml - cp ./hack/ci/e2e-conformance/metadata.yaml ./out/bootstrap-kubeadm/v${E2E_CAPI_VERSION}/metadata.yaml - - mkdir -p ./out/control-plane-kubeadm/v${E2E_CAPI_VERSION} - wget https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/${E2E_CAPI_DOWNLOAD_VERSION}/control-plane-components.yaml -O ./out/control-plane-kubeadm/v${E2E_CAPI_VERSION}/control-plane-components.yaml - cp ./hack/ci/e2e-conformance/metadata.yaml ./out/control-plane-kubeadm/v${E2E_CAPI_VERSION}/metadata.yaml - - # Generate cluster.yaml - OPENSTACK_FAILURE_DOMAIN=${OPENSTACK_FAILURE_DOMAIN} \ - OPENSTACK_CLOUD=${OPENSTACK_CLOUD} \ - OPENSTACK_CLOUD_CACERT_B64=${OPENSTACK_CLOUD_CACERT_B64} \ - OPENSTACK_CLOUD_PROVIDER_CONF_B64=${OPENSTACK_CLOUD_PROVIDER_CONF_B64} \ - OPENSTACK_CLOUD_YAML_B64=${OPENSTACK_CLOUD_YAML_B64} \ - OPENSTACK_DNS_NAMESERVERS=${OPENSTACK_DNS_NAMESERVERS} \ - OPENSTACK_IMAGE_NAME=${OPENSTACK_IMAGE_NAME} \ - OPENSTACK_SSH_KEY_NAME=${OPENSTACK_SSH_KEY_NAME} \ - OPENSTACK_NODE_MACHINE_FLAVOR=${OPENSTACK_NODE_MACHINE_FLAVOR} \ - OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR=${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} \ - ./hack/tools/bin/clusterctl config cluster "${CLUSTER_NAME}" \ - --from="${OPENSTACK_CLUSTER_TEMPLATE}" \ - --kubernetes-version "${KUBERNETES_VERSION}" \ - --target-namespace "${CLUSTER_NAME}" \ - --control-plane-machine-count="${CONTROL_PLANE_MACHINE_COUNT}" \ - --worker-machine-count="${WORKER_MACHINE_COUNT}" > ./hack/ci/e2e-conformance/cluster.yaml - - # Patch cluster.yaml - < ./hack/ci/e2e-conformance/e2e-conformance_patch.yaml.tpl \ - sed "s|\${OPENSTACK_CLOUD_PROVIDER_CONF_B64}|${OPENSTACK_CLOUD_PROVIDER_CONF_B64}|" | \ - sed "s|\${OPENSTACK_CLOUD_CACERT_B64}|${OPENSTACK_CLOUD_CACERT_B64}|" | \ - sed "s|\${USE_CI_ARTIFACTS}|${USE_CI_ARTIFACTS}|" | \ - sed "s|\${IMAGE_REPOSITORY}|${IMAGE_REPOSITORY}|" | \ - sed "s|\${KUBERNETES_VERSION}|${KUBERNETES_VERSION}|" | \ - sed "s|\${CLUSTER_NAME}|${CLUSTER_NAME}|" | \ - sed "s|\${OPENSTACK_BASTION_MACHINE_FLAVOR}|${OPENSTACK_BASTION_MACHINE_FLAVOR}|" | \ - sed "s|\${OPENSTACK_BASTION_IMAGE_NAME}|${OPENSTACK_BASTION_IMAGE_NAME}|" | \ - sed "s|\${OPENSTACK_SSH_KEY_NAME}|${OPENSTACK_SSH_KEY_NAME}|" | \ - sed "s|\${OPENSTACK_SSH_KEY_PUBLIC}|${OPENSTACK_SSH_KEY_PUBLIC}|" \ - > ./hack/ci/e2e-conformance/e2e-conformance_patch.yaml - - ./hack/tools/bin/kustomize build --reorder=none hack/ci/e2e-conformance > ./out/cluster.yaml - - if ! kind get clusters | grep -q clusterapi - then - kind create cluster --name=clusterapi - fi - - echo "loading capi image into kind cluster ..." - kind --name=clusterapi load docker-image "gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:dev" - - # Delete already deployed provider - set -x - ./hack/tools/bin/clusterctl delete --all || true - ./hack/tools/bin/clusterctl delete --infrastructure openstack --include-namespace --namespace capo-system || true - kubectl delete ns capi-kubeadm-bootstrap-system capi-kubeadm-control-plane-system capi-system || true - kubectl wait --for=delete --timeout=5m ns/capo-system ns/capi-kubeadm-bootstrap-system ns/capi-kubeadm-control-plane-system ns/capi-system || true - - # Deploy provider - ./hack/tools/bin/clusterctl init --config ./out/clusterctl.yaml --infrastructure openstack --core cluster-api:v${E2E_CAPI_VERSION} --bootstrap kubeadm:v${E2E_CAPI_VERSION} --control-plane kubeadm:v${E2E_CAPI_VERSION} - - # Wait for CAPI pods - kubectl wait --for=condition=Ready --timeout=5m -n capi-system pod --all - kubectl wait --for=condition=Ready --timeout=5m -n capi-kubeadm-bootstrap-system pod --all - kubectl wait --for=condition=Ready --timeout=5m -n capi-kubeadm-control-plane-system pod --all - kubectl wait --for=condition=Ready --timeout=5m -n capo-system pod --all - - # Wait for CAPO CRDs - kubectl wait --for condition=established --timeout=60s crds/openstackmachines.infrastructure.cluster.x-k8s.io - kubectl wait --for condition=established --timeout=60s crds/openstackmachinetemplates.infrastructure.cluster.x-k8s.io - kubectl wait --for condition=established --timeout=60s crds/openstackclusters.infrastructure.cluster.x-k8s.io - - # Wait until everything is really ready, as we had some problems with pods being ready but not yet - # available when deploying the cluster. - sleep 5 - - # Deploy cluster - kubectl create ns "${CLUSTER_NAME}" || true - kubectl apply -f ./out/cluster.yaml - - # Wait for the kubeconfig to become available. - - timeout 300 bash -c "while ! kubectl -n ${CLUSTER_NAME} get secrets | grep ${CLUSTER_NAME}-kubeconfig; do kubectl -n ${CLUSTER_NAME} get secrets; sleep 10; done" - # Get kubeconfig and store it locally. - kubectl -n "${CLUSTER_NAME}" get secrets "${CLUSTER_NAME}-kubeconfig" -o json | jq -r .data.value | base64 --decode > ./kubeconfig - timeout 900 bash -c "while ! kubectl --kubeconfig=./kubeconfig get nodes | grep control-plane; do kubectl --kubeconfig=./kubeconfig get nodes; sleep 10; done" - - # Deploy calico - curl https://docs.projectcalico.org/manifests/calico.yaml | sed "s/veth_mtu:.*/veth_mtu: \"1430\"/g" | \ - kubectl --kubeconfig=./kubeconfig apply -f - - - # Wait till all machines are running (bail out at 30 mins) - attempt=0 - while true; do - kubectl -n "${CLUSTER_NAME}" get machines - # shellcheck disable=SC2046 - read -r running total <<< $(kubectl -n "${CLUSTER_NAME}" get machines \ - -o json | jq -r '.items[].status.phase' | awk 'BEGIN{count=0} /(r|R)unning/{count++} END{print count " " NR}') ; - if [[ ${total} == "${running}" ]]; then - return 0 - fi - # shellcheck disable=SC2046 - read -r failed total <<< $(kubectl -n "${CLUSTER_NAME}" get machines \ - -o json | jq -r '.items[].status.phase' | awk 'BEGIN{count=0} /(f|F)ailed/{count++} END{print count " " NR}') ; - if [[ ! ${failed} -eq 0 ]]; then - echo "$failed machines (out of $total) in cluster failed ... bailing out" - exit 1 - fi - timestamp=$(date +"[%H:%M:%S]") - if [[ ${attempt} -gt 180 ]]; then - echo "cluster did not start in 30 mins ... bailing out!" - exit 1 - fi - echo "$timestamp Total machines : $total / Running : $running .. waiting for 10 seconds" - sleep 10 - attempt=$((attempt+1)) - done - - # Wait till all pods and nodes are ready - kubectl --kubeconfig=./kubeconfig wait --for=condition=Ready --timeout=15m pods -n kube-system --all - kubectl --kubeconfig=./kubeconfig wait --for=condition=Ready --timeout=5m node --all -} - -delete_cluster() { - kubectl -n "${CLUSTER_NAME}" delete cluster --all --ignore-not-found - kubectl -n "${CLUSTER_NAME}" get machinedeployment,kubeadmcontrolplane,cluster - - if [[ $(kubectl -n "${CLUSTER_NAME}" get machinedeployment,kubeadmcontrolplane,cluster | wc -l) -gt 0 ]] - then - echo "Error: not all resources have been deleted correctly" - exit 1 - fi -} - -# run e2es with kubetest -run_tests() { - # export the KUBECONFIG - KUBECONFIG="${PWD}/kubeconfig" - export KUBECONFIG - - # ginkgo regexes - SKIP="${SKIP:-}" - FOCUS="${FOCUS:-"\\[Conformance\\]"}" - # if we set PARALLEL=true, skip serial tests set --ginkgo-parallel - if [[ "${PARALLEL:-false}" == "true" ]]; then - export GINKGO_PARALLEL=y - export GINKGO_PARALLEL_NODES=5 - echo "Running tests in parallel" - if [[ -z "${SKIP}" ]]; then - SKIP="\\[Serial\\]" - else - SKIP="\\[Serial\\]|${SKIP}" - fi - fi - - # get the number of worker nodes - # TODO(bentheelder): this is kinda gross - NUM_NODES="$(kubectl get nodes --kubeconfig="$KUBECONFIG" \ - -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints}{"\n"}{end}' \ - | grep -cv "node-role.kubernetes.io/master" )" - - # setting this env prevents ginkgo e2e from trying to run provider setup - export KUBERNETES_CONFORMANCE_TEST="y" - # run the tests - (cd "$(go env GOPATH)/src/k8s.io/kubernetes" && ./hack/ginkgo-e2e.sh \ - '--provider=skeleton' "--num-nodes=${NUM_NODES}" \ - "--ginkgo.focus=${FOCUS}" "--ginkgo.skip=${SKIP}" \ - "--report-dir=${ARTIFACTS}" '--disable-log-dump=true' | tee "${ARTIFACTS}/e2e.log") - - unset KUBECONFIG - unset KUBERNETES_CONFORMANCE_TEST -} - -# setup kind, build kubernetes, create a cluster, run the e2es -main() { - for arg in "$@" - do - if [[ "$arg" == "--verbose" ]]; then - set -o xtrace - fi - if [[ "$arg" == "--skip-install-prereqs" ]]; then - SKIP_INSTALL_PREREQS="1" - fi - if [[ "$arg" == "--skip-build" ]]; then - SKIP_BUILD="1" - fi - if [[ "$arg" == "--skip-cleanup" ]]; then - SKIP_CLEANUP="1" - fi - if [[ "$arg" == "--use-ci-artifacts" ]]; then - USE_CI_ARTIFACTS="true" - fi - if [[ "$arg" == "--skip-upload-image" ]]; then - SKIP_UPLOAD_IMAGE="1" - fi - if [[ "$arg" == "--skip-run-tests" ]]; then - SKIP_RUN_TESTS="1" - fi - if [[ "$arg" == "--run-tests-parallel" ]]; then - export PARALLEL="true" - fi - if [[ "$arg" == "--skip-delete-cluster" ]]; then - SKIP_DELETE_CLUSTER="1" - fi - done - - # ensure artifacts exists when not in CI - export ARTIFACTS - mkdir -p "${ARTIFACTS}/logs" - - source "${REPO_ROOT}/hack/ensure-go.sh" - source "${REPO_ROOT}/hack/ensure-kind.sh" - source "${REPO_ROOT}/hack/ensure-kubectl.sh" - - export GOPATH=${GOPATH:-/home/ubuntu/go} - export PATH=$PATH:${GOPATH}/bin:/snap/bin:${HOME}/bin - - if [[ -z "${SKIP_INSTALL_PREREQS:-}" ]]; then - echo "Install prereqs..." - install_prereqs - fi - - # setup cleanup - SKIP_CLEANUP=${SKIP_CLEANUP:-""} - if [[ -z "${SKIP_CLEANUP}" ]]; then - trap dump_logs EXIT - fi - - # exports the b64 env vars used below - # We also need CAPO_AUTH_URL to get files from the devstack later - source "${REPO_ROOT}"/templates/env.rc "${OPENSTACK_CLOUD_YAML_FILE}" "${CLUSTER_NAME}" - cp "${OPENSTACK_CLOUD_YAML_FILE}" ./ - export OS_CLOUD=${CLUSTER_NAME} - - if [[ -z "${SKIP_UPLOAD_IMAGE:-}" ]]; then - echo "Uploading image..." - upload_image "${OPENSTACK_IMAGE_NAME}" "${IMAGE_URL}" - upload_image "${OPENSTACK_BASTION_IMAGE_NAME}" "${CIRROS_URL}" - fi - - if [[ -z "${SKIP_BUILD:-}" ]]; then - echo "Building..." - build - fi - - create_key_pair - create_cluster - - if [[ -z "${SKIP_RUN_TESTS:-}" ]]; then - echo "Running tests..." - run_tests - fi - - if [[ -z "${SKIP_DELETE_CLUSTER:-}" ]]; then - echo "Dumping logs" - dump_logs - - echo "Deleting cluster..." - delete_cluster - fi -} - -main "$@" diff --git a/hack/ci/e2e-conformance/.gitignore b/hack/ci/e2e-conformance/.gitignore deleted file mode 100644 index 0c83aa43a1..0000000000 --- a/hack/ci/e2e-conformance/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cluster.yaml -e2e-conformance_patch.yaml diff --git a/hack/ci/e2e-conformance/clusterctl.yaml.tpl b/hack/ci/e2e-conformance/clusterctl.yaml.tpl deleted file mode 100644 index aa07e91730..0000000000 --- a/hack/ci/e2e-conformance/clusterctl.yaml.tpl +++ /dev/null @@ -1,13 +0,0 @@ -providers: -- name: openstack - type: InfrastructureProvider - url: ${PWD}/out/infrastructure-openstack/${E2E_CAPO_VERSION}/infrastructure-components.yaml -- name: cluster-api - type: CoreProvider - url: ${PWD}/out/cluster-api/v${E2E_CAPI_VERSION}/core-components.yaml -- name: kubeadm - type: BootstrapProvider - url: ${PWD}/out/bootstrap-kubeadm/v${E2E_CAPI_VERSION}/bootstrap-components.yaml -- name: kubeadm - type: ControlPlaneProvider - url: ${PWD}/out/control-plane-kubeadm/v${E2E_CAPI_VERSION}/control-plane-components.yaml diff --git a/hack/ci/e2e-conformance/e2e-conformance_patch.yaml.tpl b/hack/ci/e2e-conformance/e2e-conformance_patch.yaml.tpl deleted file mode 100644 index 361f136744..0000000000 --- a/hack/ci/e2e-conformance/e2e-conformance_patch.yaml.tpl +++ /dev/null @@ -1,167 +0,0 @@ -apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 -kind: OpenStackCluster -metadata: - name: ${CLUSTER_NAME} - namespace: ${CLUSTER_NAME} -spec: - bastion: - enabled: true - instance: - flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR} - image: ${OPENSTACK_BASTION_IMAGE_NAME} - sshKeyName: ${OPENSTACK_SSH_KEY_NAME} ---- -apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 -kind: KubeadmControlPlane -metadata: - name: "${CLUSTER_NAME}-control-plane" - namespace: ${CLUSTER_NAME} -spec: - kubeadmConfigSpec: - clusterConfiguration: - imageRepository: ${IMAGE_REPOSITORY} - initConfiguration: - nodeRegistration: - kubeletExtraArgs: - v: "8" - joinConfiguration: - nodeRegistration: - kubeletExtraArgs: - v: "8" - verbosity: 8 - preKubeadmCommands: - - bash -c /tmp/kubeadm-bootstrap.sh - files: - - path: /etc/kubernetes/cloud.conf - owner: root - permissions: "0600" - content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} - encoding: base64 - - path: /etc/certs/cacert - owner: root - permissions: "0600" - content: ${OPENSTACK_CLOUD_CACERT_B64} - encoding: base64 - - path: /tmp/kubeadm-bootstrap.sh - owner: "root:root" - permissions: "0744" - content: | - #!/bin/bash - - set -o nounset - set -o pipefail - set -o errexit - set -e - - [[ ${USE_CI_ARTIFACTS} == "false" ]] && exit 0 - - [[ $(id -u) != 0 ]] && SUDO="sudo" || SUDO="" - - # This script installs kubectl, kubelet, and kubeadm binaries. - LINE_SEPARATOR="*************************************************" - echo "$LINE_SEPARATOR" - - K8S_DIR="/tmp/k8s" - mkdir -p ${K8S_DIR} - K8S_URL="https://storage.googleapis.com/kubernetes-release/release/${KUBERNETES_VERSION}/kubernetes-server-linux-amd64.tar.gz" - cd ${K8S_DIR} - wget -q ${K8S_URL} - tar zxf kubernetes-server-linux-amd64.tar.gz - K8S_SERVER_BIN_DIR="${K8S_DIR}/kubernetes/server/bin" - - declare -a BINARIES_TO_TEST=("kubectl" "kubelet" "kubeadm") - for BINARY in "${BINARIES_TO_TEST[@]}"; do - # move old binary away to avoid err "Text file busy" - ${SUDO} mv /usr/bin/${BINARY} /usr/bin/${BINARY}.bak - ${SUDO} cp ${K8S_SERVER_BIN_DIR}/${BINARY} /usr/bin/${BINARY} - ${SUDO} chmod +x /usr/bin/${BINARY} - done - - echo "$(date): checking binary versions" - echo "ctr version: " $(ctr version) - echo "kubeadm version: " $(kubeadm version -o=short) - echo "kubectl version: " $(kubectl version --client=true --short=true) - echo "kubelet version: " $(kubelet --version) - - echo "$LINE_SEPARATOR" - users: - - name: "capi" - sudo: "ALL=(ALL) NOPASSWD:ALL" - # user: capi, passwd: capi - passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" - lockPassword: false - sshAuthorizedKeys: - - "${OPENSTACK_SSH_KEY_PUBLIC}" ---- -apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 -kind: KubeadmConfigTemplate -metadata: - name: ${CLUSTER_NAME}-md-0 - namespace: ${CLUSTER_NAME} -spec: - template: - spec: - verbosity: 8 - preKubeadmCommands: - - bash -c /tmp/kubeadm-bootstrap.sh - files: - - content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} - encoding: base64 - owner: root - path: /etc/kubernetes/cloud.conf - permissions: "0600" - - content: ${OPENSTACK_CLOUD_CACERT_B64} - encoding: base64 - owner: root - path: /etc/certs/cacert - permissions: "0600" - - path: /tmp/kubeadm-bootstrap.sh - owner: "root:root" - permissions: "0744" - content: | - #!/bin/bash - - set -o nounset - set -o pipefail - set -o errexit - set -e - - [[ ${USE_CI_ARTIFACTS} == "false" ]] && exit 0 - - [[ $(id -u) != 0 ]] && SUDO="sudo" || SUDO="" - - # This script installs kubectl, kubelet, and kubeadm binaries. - LINE_SEPARATOR="*************************************************" - echo "$LINE_SEPARATOR" - - K8S_DIR=/tmp/k8s - mkdir -p $K8S_DIR - K8S_URL="https://dl.k8s.io/${KUBERNETES_VERSION}/kubernetes-server-linux-amd64.tar.gz" - cd ${K8S_DIR} - wget -q ${K8S_URL} - tar zxvf kubernetes-server-linux-amd64.tar.gz - K8S_SERVER_BIN_DIR="${K8S_DIR}/kubernetes/server/bin" - - declare -a BINARIES_TO_TEST=("kubectl" "kubelet" "kubeadm") - for BINARY in "${BINARIES_TO_TEST[@]}"; do - # move old binary away to avoid err "Text file busy" - ${SUDO} mv /usr/bin/${BINARY} /usr/bin/${BINARY}.bak - ${SUDO} cp ${K8S_SERVER_BIN_DIR}/${BINARY} /usr/bin/${BINARY} - ${SUDO} chmod +x /usr/bin/${BINARY} - done - - echo "$(date): checking binary versions" - echo "ctr version: " $(ctr version) - echo "kubeadm version: " $(kubeadm version -o=short) - echo "kubectl version: " $(kubectl version --client=true --short=true) - echo "kubelet version: " $(kubelet --version) - - echo "$LINE_SEPARATOR" - users: - - name: "capi" - sudo: "ALL=(ALL) NOPASSWD:ALL" - # user: capi, passwd: capi - passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" - lockPassword: false - sshAuthorizedKeys: - - "${OPENSTACK_SSH_KEY_PUBLIC}" \ No newline at end of file diff --git a/hack/ci/e2e-conformance/kustomization.yaml b/hack/ci/e2e-conformance/kustomization.yaml deleted file mode 100644 index 2109ed6d1b..0000000000 --- a/hack/ci/e2e-conformance/kustomization.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- cluster.yaml -patchesStrategicMerge: -- e2e-conformance_patch.yaml diff --git a/hack/ci/e2e-conformance/metadata.yaml b/hack/ci/e2e-conformance/metadata.yaml deleted file mode 100644 index b71e3c35f4..0000000000 --- a/hack/ci/e2e-conformance/metadata.yaml +++ /dev/null @@ -1,4 +0,0 @@ -releaseSeries: -- major: 0 - minor: 4 - contract: v1alpha4 diff --git a/hack/tools/Makefile b/hack/tools/Makefile new file mode 100644 index 0000000000..2d4bb4a68d --- /dev/null +++ b/hack/tools/Makefile @@ -0,0 +1,79 @@ +# Copyright 2021 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. + +ROOT_DIR_RELATIVE := ../.. +include $(ROOT_DIR_RELATIVE)/common.mk + +UNAME := $(shell uname -s) + +# Directories. +BIN_DIR := bin + +OS := $(shell go env GOOS) + +## -------------------------------------- +## Tooling Binaries +## -------------------------------------- + +$(BIN_DIR): + mkdir -p $@ + +CONTROLLER_GEN := $(BIN_DIR)/controller-gen +$(CONTROLLER_GEN): $(BIN_DIR) go.mod go.sum # Build controller-gen from tools folder. + go build -tags=tools -o $@ sigs.k8s.io/controller-tools/cmd/controller-gen + +CONVERSION_GEN := $(BIN_DIR)/conversion-gen +$(CONVERSION_GEN): $(BIN_DIR) go.mod go.sum + go build -tags=tools -o $@ k8s.io/code-generator/cmd/conversion-gen + +DEFAULTER_GEN := $(BIN_DIR)/defaulter-gen +$(DEFAULTER_GEN): $(BIN_DIR) go.mod go.sum + go build -tags=tools -o $@ k8s.io/code-generator/cmd/defaulter-gen + +ENVSUBST := $(BIN_DIR)/envsubst +$(ENVSUBST): $(BIN_DIR) go.mod go.sum # Build envsubst from tools folder. + go build -tags=tools -o $@ github.com/a8m/envsubst/cmd/envsubst + +GINKGO := $(BIN_DIR)/ginkgo +$(GINKGO): $(BIN_DIR) go.mod go.sum + go build -tags=tools -o $@ github.com/onsi/ginkgo/ginkgo + +GOJQ := $(BIN_DIR)/gojq +$(GOJQ): $(BIN_DIR) go.mod go.sum + go build -tags=tools -o $@ github.com/itchyny/gojq/cmd/gojq + +GOLANGCI_LINT := $(BIN_DIR)/golangci-lint +$(GOLANGCI_LINT): $(BIN_DIR) go.mod go.sum # Build golangci-lint from tools folder. + go build -tags=tools -o $@ github.com/golangci/golangci-lint/cmd/golangci-lint + +KIND := $(BIN_DIR)/kind +$(KIND): $(BIN_DIR) go.mod go.sum + go build -tags tools -o $@ sigs.k8s.io/kind + +KUSTOMIZE := $(BIN_DIR)/kustomize +$(KUSTOMIZE): $(BIN_DIR) go.mod go.sum # Build kustomize from tools folder. + CGO_ENABLED=0 go build -tags=tools -o $@ sigs.k8s.io/kustomize/kustomize/v3 + +MOCKGEN := $(BIN_DIR)/mockgen +$(MOCKGEN): $(BIN_DIR) go.mod go.sum # Build mockgen from tools folder. + go build -tags=tools -o $@ github.com/golang/mock/mockgen + +RELEASE_NOTES := $(BIN_DIR)/release-notes +$(RELEASE_NOTES): $(BIN_DIR) go.mod go.sum + go build -tags tools -o $@ sigs.k8s.io/cluster-api/hack/tools/release + +.PHONY: clean +clean: ## Remove all tools + rm -rf bin + rm -rf share diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 6a88908a75..ffae2fa349 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -4,15 +4,18 @@ go 1.16 require ( github.com/a8m/envsubst v1.2.0 - github.com/go-openapi/spec v0.19.5 // indirect github.com/golang/mock v1.4.4 github.com/golangci/golangci-lint v1.27.0 + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/onsi/ginkgo v1.15.0 + golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect k8s.io/code-generator v0.21.0-beta.0 - sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c - sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210305093021-046ab290ba3c + sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4 + sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210313163703-752c727cf58b sigs.k8s.io/controller-tools v0.5.0 sigs.k8s.io/kind v0.9.0 + sigs.k8s.io/kustomize/kustomize/v3 v3.8.6 sigs.k8s.io/testing_frameworks v0.1.2 ) diff --git a/hack/tools/go.sum b/hack/tools/go.sum index 82efadd0b5..39b4d6b26f 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -23,23 +23,31 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -54,7 +62,9 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -67,6 +77,7 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/a8m/envsubst v1.2.0 h1:yvzAhJD2QKdo35Ut03wIfXQmg+ta3wC/1bskfZynz+Q= github.com/a8m/envsubst v1.2.0/go.mod h1:PpvLvNWa+Rvu/10qXmFbFiGICIU5hZvFJNPCCkUaObg= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -75,6 +86,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alessio/shellescape v1.2.2 h1:8LnL+ncxhWT2TR00dfJRT25JWWrhkMZXneHVWnetDZg= github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -84,6 +97,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -92,6 +107,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= @@ -133,6 +150,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -141,17 +160,21 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a h1:pf3CyiWgjOLL7cjFos89AEOPCWSOoQt7tgbEk/SvBAg= github.com/drone/envsubst v1.0.3-0.20200709223903-efdb65b94e5a/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= -github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw= -github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= +github.com/drone/envsubst/v2 v2.0.0-20210305151453-490366e43a3c/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -162,6 +185,7 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -184,10 +208,14 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-critic/go-critic v0.4.1 h1:4DTQfT1wWwLg/hzxwD9bkdhDQrdJtxe6DUTadPlrIeE= github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -206,23 +234,63 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5 h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4 h1:csnOgcgAiuGoM/Po7PEpKDoNulCcF3FGbSnbHfxgjMI= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw= github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.8 h1:YFzsdWIDfVuLvIOF+ZmKjVg1MbPJ1QgY9PihMwei1ys= +github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= @@ -255,6 +323,7 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -335,6 +404,7 @@ github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4r github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -346,6 +416,8 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= @@ -357,6 +429,7 @@ github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTV github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.4 h1:ynbQIWjLw7iv6HAFdixb30U7Uvcmx+f4KlLJpmhkTK0= github.com/googleapis/gnostic v0.5.4/go.mod h1:TRWw1s4gxBGjSe301Dai3c7wXJAZy57+/6tawkOvqHQ= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -380,15 +453,21 @@ github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoP github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -423,6 +502,7 @@ github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xl github.com/joelanford/go-apidiff v0.0.0-20191206194835-106bcff5f060/go.mod h1:wgVWgVCwYYkjcYpJtBnWYkyUYZfVovO3Y5pX49mJsqs= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -453,13 +533,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -477,6 +557,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= @@ -495,8 +577,10 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -510,6 +594,7 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= @@ -525,9 +610,13 @@ github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/f github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -545,17 +634,22 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 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= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -585,6 +679,7 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -599,6 +694,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -635,6 +731,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA= +github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/raviqqe/liche v0.0.0-20200229003944-f57a5d1c5be4/go.mod h1:MPBuzBAJcp9B/3xrqfgR+ieBgpMzDqTeieaRP3ESJhk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -650,6 +748,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83 h1:AtnWoOvTioyDXFvu96MWEeE8qj4COSQnJogzLy/u41A= github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= @@ -702,7 +801,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -710,6 +811,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -718,6 +821,8 @@ github.com/tommy-muehle/go-mnd v1.1.1 h1:4D0wuPKjOTiK2garzuPGGvm4zZ/wLYDOH8TJSAB github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= +github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= @@ -731,22 +836,34 @@ github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk github.com/valyala/fasthttp v1.9.1-0.20200228200348-695f713fcf59/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM= +github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -767,13 +884,17 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -814,10 +935,12 @@ golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -826,6 +949,7 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -879,11 +1003,13 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -897,6 +1023,7 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -921,8 +1048,9 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY= +golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -948,6 +1076,7 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -962,6 +1091,7 @@ golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1076,8 +1206,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -1106,9 +1237,11 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= @@ -1121,12 +1254,16 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= +k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= k8s.io/api v0.21.0-beta.0 h1:/FHKhlPpRSNBf76PpBsXM3UgjoY0meDsfxbnPCMZ5k4= k8s.io/api v0.21.0-beta.0/go.mod h1:3WblMF9mf/mKU1KxrpPzzNy8NKsVBaeTEnLWd2mdNho= k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs= k8s.io/apiextensions-apiserver v0.21.0-beta.0 h1:E1mtfiXVHhlH3xxUUo4LQDwLd+kWbD6x44/MCv7KeLA= k8s.io/apiextensions-apiserver v0.21.0-beta.0/go.mod h1:FLkR4wOt263zuWZgmvaAoWmcyjP9v8wgwEpiQWkyTac= +k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.21.0-beta.0 h1:uxtP+amYYfUXq3BP2s+DZrMWM+bW4uSmbTclEyEig0k= @@ -1135,6 +1272,8 @@ k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA= k8s.io/apiserver v0.21.0-beta.0 h1:hju2OFwk4LbMmC0xUZRaUM8jZ6UK2pvuDUKlIE9MVOA= k8s.io/apiserver v0.21.0-beta.0/go.mod h1:Hv+8ofeIhvh1LDGtZbE44rO90xMLP90mbWljONN2VsU= k8s.io/cli-runtime v0.21.0-beta.0/go.mod h1:bjabvs6Mlpghx/IlhnpjWrHjUgdLevcaGdxC91ZFS+Y= +k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= +k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ= k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE= k8s.io/client-go v0.21.0-beta.0 h1:QWdwWTz4v2MCKiV7dSoyslShJBMKjE5tvcQLxPQX45k= k8s.io/client-go v0.21.0-beta.0/go.mod h1:aB1a6VgwO+7U2mTowMjLAdJHFaUId8ueS1sZRn4hd64= @@ -1153,6 +1292,7 @@ k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAE k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= @@ -1160,12 +1300,14 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI= k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kubectl v0.21.0-beta.0 h1:SetOieJ21JuYuKWH/2ne1+ZcAB1QlyOFINW3YzCnw7A= k8s.io/kubectl v0.21.0-beta.0/go.mod h1:Q2RVzweq7M8aDMyGt/SjtXFet6prIbswYIKroS5iTK4= k8s.io/metrics v0.21.0-beta.0/go.mod h1:CxmOLYHLm4LTDQ+aijh2Sx4I2wTWgx2VjB6l7Jtbgro= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ= k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= @@ -1180,10 +1322,10 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c h1:Fva2ZI/os4dotzdD+zk+Rovv3A01JovSMDgvGfUc7nE= -sigs.k8s.io/cluster-api v0.3.11-0.20210305093021-046ab290ba3c/go.mod h1:pww0lCxSkEXcDzkKYikhJ8k9MuFvLZAmLY6rFokvaZk= -sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210305093021-046ab290ba3c h1:4UgxNmRUb5KdFiObKkQnMHUpduk/FSinbjkXQ6QFPb0= -sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210305093021-046ab290ba3c/go.mod h1:6CnFB2ywSwiM4CQhgprfGFh4VTl5eLLN/swgsycLNzA= +sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4 h1:HiLm4yLlJad40oOZdMASQgXKNQ9LE5GkQ5qK0pBRX+4= +sigs.k8s.io/cluster-api v0.3.11-0.20210310224224-a9144a861bf4/go.mod h1:pww0lCxSkEXcDzkKYikhJ8k9MuFvLZAmLY6rFokvaZk= +sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210313163703-752c727cf58b h1:xxPcrotkrh+R9f2znX7NHsqvXa0HdLiErEjHwH1TW4U= +sigs.k8s.io/cluster-api/hack/tools v0.0.0-20210313163703-752c727cf58b/go.mod h1:vau/MPstGwnCi6WifwEIIBiJuQMWsAKVIkLVQjnjKHg= sigs.k8s.io/controller-runtime v0.8.2-0.20210302195120-85527dfb5348 h1:9iK3tArPJp/PYbqUjzpjZJ94KGGOHhvloa4N0RzeZi8= sigs.k8s.io/controller-runtime v0.8.2-0.20210302195120-85527dfb5348/go.mod h1:WSqdxdrtK8mVoszWTAw0Jg3zfyHwvT8nn3B5tA2Hkms= sigs.k8s.io/controller-tools v0.5.0 h1:3u2RCwOlp0cjCALAigpOcbAf50pE+kHSdueUosrC/AE= @@ -1191,7 +1333,18 @@ sigs.k8s.io/controller-tools v0.5.0/go.mod h1:JTsstrMpxs+9BUj6eGuAaEb6SDSPTeVtUy sigs.k8s.io/kind v0.9.0 h1:SoDlXq6pEc7dGagHULNRCCBYrLH6xOi7lqXTRXeAlg4= sigs.k8s.io/kind v0.9.0/go.mod h1:cxKQWwmbtRDzQ+RNKnR6gZG6fjbeTtItp5cGf+ww+1Y= sigs.k8s.io/kubebuilder/docs/book/utils v0.0.0-20200226075303-ed8438ec10a4/go.mod h1:nyAxPBUS04gN3IRuEQ0elG4mVeto/d/qQRsW2PsyAy4= +sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= +sigs.k8s.io/kustomize/api v0.6.4 h1:YIVJnBH+yngw1/1CcLH6GvJ2aEoX9jDlqVuWhfjWmYc= +sigs.k8s.io/kustomize/api v0.6.4/go.mod h1:BX11EGGdQTCYHLMaz7oT4TKdQ8owypNlYIrUj1i5HwA= +sigs.k8s.io/kustomize/cmd/config v0.8.4 h1:Lo26VjENBVfAOJu0v6w6C1cv5Zp9K8XRs39/0cb87+k= +sigs.k8s.io/kustomize/cmd/config v0.8.4/go.mod h1:1+URiyIJrjdxCdCNDuh2SLyf+I36txRgubFI3PIg2Gc= +sigs.k8s.io/kustomize/kustomize/v3 v3.8.6 h1:QmnslC85Qvi7onieAL5OF2gWu6BZXns+N3gWJAFkpys= +sigs.k8s.io/kustomize/kustomize/v3 v3.8.6/go.mod h1:xdsZQdh9dxB0xI+gv6K0nJuPYt1S+9O6K4Su1HXJTHM= +sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I= +sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= diff --git a/hack/tools/tools.go b/hack/tools/tools.go index 6a618f74d7..57fcdb69df 100644 --- a/hack/tools/tools.go +++ b/hack/tools/tools.go @@ -29,5 +29,6 @@ import ( _ "sigs.k8s.io/cluster-api/hack/tools/release" _ "sigs.k8s.io/controller-tools/cmd/controller-gen" _ "sigs.k8s.io/kind" + _ "sigs.k8s.io/kustomize/kustomize/v3" _ "sigs.k8s.io/testing_frameworks/integration" ) diff --git a/metadata.yaml b/metadata.yaml index bb15d021f8..b61e48c523 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,4 +1,4 @@ -apiVersion: clusterctl.cluster.x-k8s.io/v1alpha4 +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 kind: Metadata releaseSeries: - major: 0 @@ -7,4 +7,3 @@ releaseSeries: - major: 0 minor: 4 contract: v1alpha4 - diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go index 9b6b31be73..8798f6147e 100644 --- a/pkg/cloud/services/compute/instance.go +++ b/pkg/cloud/services/compute/instance.go @@ -297,7 +297,7 @@ func serverToInstance(v *servers.Server) (*infrav1.Instance, error) { SSHKeyName: v.KeyName, State: infrav1.InstanceState(v.Status), } - addrMap, err := getIPFromInstance(v) + addrMap, err := GetIPFromInstance(*v) if err != nil { return i, err } @@ -308,7 +308,7 @@ func serverToInstance(v *servers.Server) (*infrav1.Instance, error) { return i, nil } -func getIPFromInstance(v *servers.Server) (map[string]string, error) { +func GetIPFromInstance(v servers.Server) (map[string]string, error) { addrMap := make(map[string]string) if v.AccessIPv4 != "" && net.ParseIP(v.AccessIPv4) != nil { addrMap["internal"] = v.AccessIPv4 @@ -675,11 +675,11 @@ func (s *Service) InstanceExists(name string) (instance *infrav1.Instance, err e allPages, err := servers.List(s.computeClient, listOpts).AllPages() if err != nil { - return nil, fmt.Errorf("get service list: %v", err) + return nil, fmt.Errorf("get server list: %v", err) } serverList, err := servers.ExtractServers(allPages) if err != nil { - return nil, fmt.Errorf("extract services list: %v", err) + return nil, fmt.Errorf("extract server list: %v", err) } instanceList := []*infrav1.Instance{} for _, server := range serverList { diff --git a/pkg/cloud/services/provider/provider.go b/pkg/cloud/services/provider/provider.go index 6f0a5974e8..2cbf568340 100644 --- a/pkg/cloud/services/provider/provider.go +++ b/pkg/cloud/services/provider/provider.go @@ -26,10 +26,10 @@ import ( "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/utils/openstack/clientconfig" - "gopkg.in/yaml.v2" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha4" ) @@ -54,7 +54,7 @@ func NewClientFromMachine(ctrlClient client.Client, openStackMachine *infrav1.Op return nil, nil, err } } - return newClient(cloud, caCert) + return NewClient(cloud, caCert) } func NewClientFromCluster(ctrlClient client.Client, openStackCluster *infrav1.OpenStackCluster) (*gophercloud.ProviderClient, *clientconfig.ClientOpts, error) { @@ -72,10 +72,10 @@ func NewClientFromCluster(ctrlClient client.Client, openStackCluster *infrav1.Op return nil, nil, err } } - return newClient(cloud, caCert) + return NewClient(cloud, caCert) } -func newClient(cloud clientconfig.Cloud, caCert []byte) (*gophercloud.ProviderClient, *clientconfig.ClientOpts, error) { +func NewClient(cloud clientconfig.Cloud, caCert []byte) (*gophercloud.ProviderClient, *clientconfig.ClientOpts, error) { clientOpts := new(clientconfig.ClientOpts) if cloud.AuthInfo != nil { clientOpts.AuthInfo = cloud.AuthInfo @@ -141,8 +141,7 @@ func getCloudFromSecret(ctrlClient client.Client, secretNamespace string, secret secretName, CloudsSecretKey) } var clouds clientconfig.Clouds - err = yaml.Unmarshal(content, &clouds) - if err != nil { + if err = yaml.Unmarshal(content, &clouds); err != nil { return emptyCloud, nil, fmt.Errorf("failed to unmarshal clouds credentials stored in secret %v: %v", secretName, err) } diff --git a/scripts/ci-build.sh b/scripts/ci-build.sh index 41198253ce..4a1cafd472 100755 --- a/scripts/ci-build.sh +++ b/scripts/ci-build.sh @@ -22,4 +22,4 @@ REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. # shellcheck source=../hack/ensure-go.sh source "${REPO_ROOT}/hack/ensure-go.sh" -cd "${REPO_ROOT}" && make binaries +cd "${REPO_ROOT}" && make binaries compile-e2e diff --git a/scripts/ci-conformance.sh b/scripts/ci-conformance.sh index 896af7d713..cd1bf1de5c 100755 --- a/scripts/ci-conformance.sh +++ b/scripts/ci-conformance.sh @@ -42,7 +42,7 @@ cleanup() { # stop boskos heartbeat [[ -z ${HEART_BEAT_PID:-} ]] || kill -9 "${HEART_BEAT_PID}" - # will be started by e2e-conformance-gcp-prepare.sh + # will be started by the devstack installation script pkill sshuttle } trap cleanup EXIT @@ -50,7 +50,7 @@ trap cleanup EXIT #Install requests module explicitly for HTTP calls python3 -m pip install requests -# If BOSKOS_HOST is set then acquire an GCP account from Boskos. +# If BOSKOS_HOST is set then acquire a resource of type ${RESOURCE_TYPE} from Boskos. if [ -n "${BOSKOS_HOST:-}" ]; then # Check out the account from Boskos and store the produced environment # variables in a temporary file. @@ -78,16 +78,14 @@ if [ -n "${BOSKOS_HOST:-}" ]; then HEART_BEAT_PID=$! fi -hack/ci/e2e-conformance-gcp-prepare.sh +"hack/ci/devstack-on-${RESOURCE_TYPE}-install.sh" -export ARTIFACTS -export OPENSTACK_DNS_NAMESERVERS=8.8.8.8 -export CONTROL_PLANE_MACHINE_COUNT=1 -export WORKER_MACHINE_COUNT=4 -hack/ci/e2e-conformance.sh --run-tests-parallel --verbose $* +export OPENSTACK_CLOUD_YAML_FILE +OPENSTACK_CLOUD_YAML_FILE="$(pwd)/clouds.yaml" +make test-conformance-fast test_status="${?}" -# If Boskos is being used then release the GCP project back to Boskos. +# If Boskos is being used then release the resource back to Boskos. [ -z "${BOSKOS_HOST:-}" ] || python3 hack/boskos.py --release >> "$ARTIFACTS/logs/boskos.log" 2>&1 exit "${test_status}" diff --git a/templates/cluster-template-external-cloud-provider.yaml b/templates/cluster-template-external-cloud-provider.yaml index 6fa35ceff8..572bf14d1e 100644 --- a/templates/cluster-template-external-cloud-provider.yaml +++ b/templates/cluster-template-external-cloud-provider.yaml @@ -3,7 +3,6 @@ apiVersion: cluster.x-k8s.io/v1alpha4 kind: Cluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: clusterNetwork: pods: @@ -22,12 +21,10 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackCluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} managedAPIServerLoadBalancer: true managedSecurityGroups: true nodeCidr: 10.6.0.0/24 @@ -39,7 +36,6 @@ kind: KubeadmControlPlane apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 metadata: name: "${CLUSTER_NAME}-control-plane" - namespace: '${NAMESPACE}' spec: replicas: ${CONTROL_PLANE_MACHINE_COUNT} infrastructureTemplate: @@ -71,7 +67,6 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-control-plane - namespace: '${NAMESPACE}' spec: template: spec: @@ -81,13 +76,11 @@ spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} --- apiVersion: cluster.x-k8s.io/v1alpha4 kind: MachineDeployment metadata: name: "${CLUSTER_NAME}-md-0" - namespace: '${NAMESPACE}' spec: clusterName: "${CLUSTER_NAME}" replicas: ${WORKER_MACHINE_COUNT} @@ -112,14 +105,12 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} @@ -128,7 +119,6 @@ apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 kind: KubeadmConfigTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: @@ -144,7 +134,6 @@ metadata: name: ${CLUSTER_NAME}-cloud-config labels: clusterctl.cluster.x-k8s.io/move: "true" - namespace: '${NAMESPACE}' data: clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} cacert: ${OPENSTACK_CLOUD_CACERT_B64} diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml index e63a9af8c1..c19794459e 100644 --- a/templates/cluster-template-without-lb.yaml +++ b/templates/cluster-template-without-lb.yaml @@ -3,7 +3,6 @@ apiVersion: cluster.x-k8s.io/v1alpha4 kind: Cluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: clusterNetwork: pods: @@ -22,12 +21,10 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackCluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} managedSecurityGroups: true nodeCidr: 10.6.0.0/24 dnsNameservers: @@ -37,7 +34,6 @@ kind: KubeadmControlPlane apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 metadata: name: "${CLUSTER_NAME}-control-plane" - namespace: '${NAMESPACE}' spec: replicas: 1 infrastructureTemplate: @@ -98,7 +94,6 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-control-plane - namespace: '${NAMESPACE}' spec: template: spec: @@ -108,13 +103,11 @@ spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} --- apiVersion: cluster.x-k8s.io/v1alpha4 kind: MachineDeployment metadata: name: "${CLUSTER_NAME}-md-0" - namespace: '${NAMESPACE}' spec: clusterName: "${CLUSTER_NAME}" replicas: ${WORKER_MACHINE_COUNT} @@ -139,14 +132,12 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} @@ -155,7 +146,6 @@ apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 kind: KubeadmConfigTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: @@ -183,7 +173,6 @@ metadata: name: ${CLUSTER_NAME}-cloud-config labels: clusterctl.cluster.x-k8s.io/move: "true" - namespace: '${NAMESPACE}' data: clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} cacert: ${OPENSTACK_CLOUD_CACERT_B64} diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml index 4ce9dccb08..c9f4f5eafe 100644 --- a/templates/cluster-template.yaml +++ b/templates/cluster-template.yaml @@ -3,7 +3,6 @@ apiVersion: cluster.x-k8s.io/v1alpha4 kind: Cluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: clusterNetwork: pods: @@ -22,12 +21,10 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackCluster metadata: name: ${CLUSTER_NAME} - namespace: '${NAMESPACE}' spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} managedAPIServerLoadBalancer: true managedSecurityGroups: true nodeCidr: 10.6.0.0/24 @@ -39,7 +36,6 @@ kind: KubeadmControlPlane apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 metadata: name: "${CLUSTER_NAME}-control-plane" - namespace: '${NAMESPACE}' spec: replicas: ${CONTROL_PLANE_MACHINE_COUNT} infrastructureTemplate: @@ -100,7 +96,6 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-control-plane - namespace: '${NAMESPACE}' spec: template: spec: @@ -110,13 +105,11 @@ spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} --- apiVersion: cluster.x-k8s.io/v1alpha4 kind: MachineDeployment metadata: name: "${CLUSTER_NAME}-md-0" - namespace: '${NAMESPACE}' spec: clusterName: "${CLUSTER_NAME}" replicas: ${WORKER_MACHINE_COUNT} @@ -141,14 +134,12 @@ apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 kind: OpenStackMachineTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: cloudName: ${OPENSTACK_CLOUD} cloudsSecret: name: ${CLUSTER_NAME}-cloud-config - namespace: ${NAMESPACE} flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} @@ -157,7 +148,6 @@ apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 kind: KubeadmConfigTemplate metadata: name: ${CLUSTER_NAME}-md-0 - namespace: '${NAMESPACE}' spec: template: spec: @@ -185,7 +175,6 @@ metadata: name: ${CLUSTER_NAME}-cloud-config labels: clusterctl.cluster.x-k8s.io/move: "true" - namespace: '${NAMESPACE}' data: clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} cacert: ${OPENSTACK_CLOUD_CACERT_B64} diff --git a/test/e2e/data/ci-artifacts-platform-kustomization.yaml b/test/e2e/data/ci-artifacts-platform-kustomization.yaml new file mode 100644 index 0000000000..d5d51d4b07 --- /dev/null +++ b/test/e2e/data/ci-artifacts-platform-kustomization.yaml @@ -0,0 +1,336 @@ +# Can be used to modify the resources when use-ci-artifacts is enabled. +--- +apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 +kind: KubeadmControlPlane +metadata: + name: ${CLUSTER_NAME}-control-plane +spec: + infrastructureTemplate: {} + kubeadmConfigSpec: + files: + # We need to add these files again, because kustomize overrides the whole array + # See: https://github.com/kubernetes-sigs/kustomize/issues/2825 + - content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" + - content: | + #!/bin/bash + + ## Please note that this file needs to be escaped for envsubst to function + + function retry { + attempt=0 + max_attempts=$${1} + interval=$${2} + shift; shift + until [[ $${attempt} -ge "$${max_attempts}" ]] ; do + attempt=$((attempt+1)) + set +e + eval "$*" && return || echo "failed $${attempt} times: $*" + set -e + sleep "$${interval}" + done + echo "error: reached max attempts at retry($*)" + return 1 + } + retry 10 5 "apt-get update" + + owner: root:root + path: /usr/local/bin/retry-apt.sh + permissions: "0750" + - content: | + #!/bin/bash + + # Copyright 2020 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. + + ## Please note that this file needs to be escaped for envsubst to function + + # shellcheck disable=SC1083,SC2034,SC2066,SC2193 + + set -o nounset + set -o pipefail + set -o errexit + + [[ $(id -u) != 0 ]] && SUDO="sudo" || SUDO="" + + USE_CI_ARTIFACTS=${USE_CI_ARTIFACTS:=false} + + if [ ! "${USE_CI_ARTIFACTS}" = true ]; then + echo "No CI Artifacts installation, exiting" + exit 0 + fi + + GSUTIL=gsutil + + if ! command -v $${GSUTIL} >/dev/null; then + apt-get update + apt-get install -y apt-transport-https ca-certificates gnupg curl + echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | $${SUDO} tee -a /etc/apt/sources.list.d/google-cloud-sdk.list + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | $${SUDO} apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - + apt-get update + apt-get install -y google-cloud-sdk + fi + + $${GSUTIL} version + + # This test installs release packages or binaries that are a result of the CI and release builds. + # It runs '... --version' commands to verify that the binaries are correctly installed + # and finally uninstalls the packages. + # For the release packages it tests all versions in the support skew. + LINE_SEPARATOR="*************************************************" + echo "$${LINE_SEPARATOR}" + + ## Clusterctl set variables + ## + # $${KUBERNETES_VERSION} will be replaced by clusterctl + KUBERNETES_VERSION=${KUBERNETES_VERSION} + ## + ## End clusterctl set variables + + if [[ "$${KUBERNETES_VERSION}" != "" ]]; then + CI_DIR=/tmp/k8s-ci + mkdir -p "$${CI_DIR}" + declare -a PACKAGES_TO_TEST=("kubectl" "kubelet" "kubeadm") + declare -a CONTAINERS_TO_TEST=("kube-apiserver" "kube-controller-manager" "kube-proxy" "kube-scheduler") + CONTAINER_EXT="tar" + echo "* testing CI version $${KUBERNETES_VERSION}" + # Check for semver + if [[ "$${KUBERNETES_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + CI_URL="gs://kubernetes-release/release/$${KUBERNETES_VERSION}/bin/linux/amd64" + VERSION_WITHOUT_PREFIX="$${KUBERNETES_VERSION#v}" + DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https curl + curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - + echo 'deb https://apt.kubernetes.io/ kubernetes-xenial main' >/etc/apt/sources.list.d/kubernetes.list + apt-get update + # replace . with \. + VERSION_REGEX="$${VERSION_WITHOUT_PREFIX//./\\.}" + PACKAGE_VERSION="$(apt-cache madison kubelet | grep "$${VERSION_REGEX}-" | head -n1 | cut -d '|' -f 2 | tr -d '[:space:]')" + for CI_PACKAGE in "$${PACKAGES_TO_TEST[@]}"; do + echo "* installing package: $${CI_PACKAGE} $${PACKAGE_VERSION}" + DEBIAN_FRONTEND=noninteractive apt-get install -y "$${CI_PACKAGE}=$${PACKAGE_VERSION}" + done + else + CI_URL="gs://kubernetes-release-dev/ci/$${KUBERNETES_VERSION}/bin/linux/amd64" + for CI_PACKAGE in "$${PACKAGES_TO_TEST[@]}"; do + echo "* downloading binary: $${CI_URL}/$${CI_PACKAGE}" + $${GSUTIL} cp "$${CI_URL}/$${CI_PACKAGE}" "$${CI_DIR}/$${CI_PACKAGE}" + chmod +x "$${CI_DIR}/$${CI_PACKAGE}" + mv "$${CI_DIR}/$${CI_PACKAGE}" "/usr/bin/$${CI_PACKAGE}" + done + systemctl restart kubelet + fi + for CI_CONTAINER in "$${CONTAINERS_TO_TEST[@]}"; do + echo "* downloading package: $${CI_URL}/$${CI_CONTAINER}.$${CONTAINER_EXT}" + $${GSUTIL} cp "$${CI_URL}/$${CI_CONTAINER}.$${CONTAINER_EXT}" "$${CI_DIR}/$${CI_CONTAINER}.$${CONTAINER_EXT}" + $${SUDO} ctr -n k8s.io images import "$${CI_DIR}/$${CI_CONTAINER}.$${CONTAINER_EXT}" || echo "* ignoring expected 'ctr images import' result" + $${SUDO} ctr -n k8s.io images tag "k8s.gcr.io/$${CI_CONTAINER}-amd64:$${KUBERNETES_VERSION//+/_}" "k8s.gcr.io/$${CI_CONTAINER}:$${KUBERNETES_VERSION//+/_}" + $${SUDO} ctr -n k8s.io images tag "k8s.gcr.io/$${CI_CONTAINER}-amd64:$${KUBERNETES_VERSION//+/_}" "gcr.io/kubernetes-ci-images/$${CI_CONTAINER}:$${KUBERNETES_VERSION//+/_}" + done + fi + echo "* checking binary versions" + echo "ctr version: " "$(ctr version)" + echo "kubeadm version: " "$(kubeadm version -o=short)" + echo "kubectl version: " "$(kubectl version --client=true --short=true)" + echo "kubelet version: " "$(kubelet --version)" + echo "$${LINE_SEPARATOR}" + owner: root:root + path: /usr/local/bin/ci-artifacts.sh + permissions: "0750" + preKubeadmCommands: + - /usr/local/bin/retry-apt.sh + - /usr/local/bin/ci-artifacts.sh + users: + - name: "capi" + sudo: "ALL=(ALL) NOPASSWD:ALL" + # user: capi, passwd: capi + passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" + lockPassword: false + version: ${KUBERNETES_VERSION} +status: + initialized: false + ready: false + +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 +kind: KubeadmConfigTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + files: + # We need to add these files again, because kustomize overrides the whole array + # See: https://github.com/kubernetes-sigs/kustomize/issues/2825 + - path: /etc/kubernetes/cloud.conf + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + - path: /etc/certs/cacert + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + - content: | + #!/bin/bash + + ## Please note that this file needs to be escaped for envsubst to function + + function retry { + attempt=0 + max_attempts=$${1} + interval=$${2} + shift; shift + until [[ $${attempt} -ge "$${max_attempts}" ]] ; do + attempt=$((attempt+1)) + set +e + eval "$*" && return || echo "failed $${attempt} times: $*" + set -e + sleep "$${interval}" + done + echo "error: reached max attempts at retry($*)" + return 1 + } + retry 10 5 "apt-get update" + + owner: root:root + path: /usr/local/bin/retry-apt.sh + permissions: "0750" + - content: | + #!/bin/bash + + # Copyright 2020 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. + + ## Please note that this file needs to be escaped for envsubst to function + + # shellcheck disable=SC1083,SC2034,SC2066,SC2193 + + set -o nounset + set -o pipefail + set -o errexit + + [[ $(id -u) != 0 ]] && SUDO="sudo" || SUDO="" + + USE_CI_ARTIFACTS=${USE_CI_ARTIFACTS:=false} + + if [ ! "${USE_CI_ARTIFACTS}" = true ]; then + echo "No CI Artifacts installation, exiting" + exit 0 + fi + + GSUTIL=gsutil + + if ! command -v $${GSUTIL} >/dev/null; then + apt-get update + apt-get install -y apt-transport-https ca-certificates gnupg curl + echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | $${SUDO} tee -a /etc/apt/sources.list.d/google-cloud-sdk.list + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | $${SUDO} apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - + apt-get update + apt-get install -y google-cloud-sdk + fi + + $${GSUTIL} version + + # This test installs release packages or binaries that are a result of the CI and release builds. + # It runs '... --version' commands to verify that the binaries are correctly installed + # and finally uninstalls the packages. + # For the release packages it tests all versions in the support skew. + LINE_SEPARATOR="*************************************************" + echo "$${LINE_SEPARATOR}" + + ## Clusterctl set variables + ## + # $${KUBERNETES_VERSION} will be replaced by clusterctl + KUBERNETES_VERSION=${KUBERNETES_VERSION} + ## + ## End clusterctl set variables + + if [[ "$${KUBERNETES_VERSION}" != "" ]]; then + CI_DIR=/tmp/k8s-ci + mkdir -p "$${CI_DIR}" + declare -a PACKAGES_TO_TEST=("kubectl" "kubelet" "kubeadm") + declare -a CONTAINERS_TO_TEST=("kube-apiserver" "kube-controller-manager" "kube-proxy" "kube-scheduler") + CONTAINER_EXT="tar" + echo "* testing CI version $${KUBERNETES_VERSION}" + # Check for semver + if [[ "$${KUBERNETES_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + CI_URL="gs://kubernetes-release/release/$${KUBERNETES_VERSION}/bin/linux/amd64" + VERSION_WITHOUT_PREFIX="$${KUBERNETES_VERSION#v}" + DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https curl + curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - + echo 'deb https://apt.kubernetes.io/ kubernetes-xenial main' >/etc/apt/sources.list.d/kubernetes.list + apt-get update + # replace . with \. + VERSION_REGEX="$${VERSION_WITHOUT_PREFIX//./\\.}" + PACKAGE_VERSION="$(apt-cache madison kubelet | grep "$${VERSION_REGEX}-" | head -n1 | cut -d '|' -f 2 | tr -d '[:space:]')" + for CI_PACKAGE in "$${PACKAGES_TO_TEST[@]}"; do + echo "* installing package: $${CI_PACKAGE} $${PACKAGE_VERSION}" + DEBIAN_FRONTEND=noninteractive apt-get install -y "$${CI_PACKAGE}=$${PACKAGE_VERSION}" + done + else + CI_URL="gs://kubernetes-release-dev/ci/$${KUBERNETES_VERSION}/bin/linux/amd64" + for CI_PACKAGE in "$${PACKAGES_TO_TEST[@]}"; do + echo "* downloading binary: $${CI_URL}/$${CI_PACKAGE}" + $${GSUTIL} cp "$${CI_URL}/$${CI_PACKAGE}" "$${CI_DIR}/$${CI_PACKAGE}" + chmod +x "$${CI_DIR}/$${CI_PACKAGE}" + mv "$${CI_DIR}/$${CI_PACKAGE}" "/usr/bin/$${CI_PACKAGE}" + done + systemctl restart kubelet + fi + for CI_CONTAINER in "$${CONTAINERS_TO_TEST[@]}"; do + echo "* downloading package: $${CI_URL}/$${CI_CONTAINER}.$${CONTAINER_EXT}" + $${GSUTIL} cp "$${CI_URL}/$${CI_CONTAINER}.$${CONTAINER_EXT}" "$${CI_DIR}/$${CI_CONTAINER}.$${CONTAINER_EXT}" + $${SUDO} ctr -n k8s.io images import "$${CI_DIR}/$${CI_CONTAINER}.$${CONTAINER_EXT}" || echo "* ignoring expected 'ctr images import' result" + $${SUDO} ctr -n k8s.io images tag "k8s.gcr.io/$${CI_CONTAINER}-amd64:$${KUBERNETES_VERSION//+/_}" "k8s.gcr.io/$${CI_CONTAINER}:$${KUBERNETES_VERSION//+/_}" + $${SUDO} ctr -n k8s.io images tag "k8s.gcr.io/$${CI_CONTAINER}-amd64:$${KUBERNETES_VERSION//+/_}" "gcr.io/kubernetes-ci-images/$${CI_CONTAINER}:$${KUBERNETES_VERSION//+/_}" + done + fi + echo "* checking binary versions" + echo "ctr version: " "$(ctr version)" + echo "kubeadm version: " "$(kubeadm version -o=short)" + echo "kubectl version: " "$(kubectl version --client=true --short=true)" + echo "kubelet version: " "$(kubelet --version)" + echo "$${LINE_SEPARATOR}" + owner: root:root + path: /usr/local/bin/ci-artifacts.sh + permissions: "0750" + preKubeadmCommands: + - /usr/local/bin/retry-apt.sh + - /usr/local/bin/ci-artifacts.sh + users: + - name: "capi" + sudo: "ALL=(ALL) NOPASSWD:ALL" + # user: capi, passwd: capi + passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" + lockPassword: false diff --git a/test/e2e/data/cni/calico.yaml b/test/e2e/data/cni/calico.yaml new file mode 100644 index 0000000000..65d06c76d5 --- /dev/null +++ b/test/e2e/data/cni/calico.yaml @@ -0,0 +1,3872 @@ +--- +# Source: calico/templates/calico-config.yaml +# This ConfigMap is used to configure a self-hosted Calico installation. +kind: ConfigMap +apiVersion: v1 +metadata: + name: calico-config + namespace: kube-system +data: + # Typha is disabled. + typha_service_name: "none" + # Configure the backend to use. + calico_backend: "bird" + + # Configure the MTU to use for workload interfaces and tunnels. + # By default, MTU is auto-detected, and explicitly setting this field should not be required. + # You can override auto-detection by providing a non-zero value. + veth_mtu: "1430" + + # The CNI network configuration to install on each node. The special + # values in this config will be automatically populated. + cni_network_config: |- + { + "name": "k8s-pod-network", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "calico", + "log_level": "info", + "log_file_path": "/var/log/calico/cni/cni.log", + "datastore_type": "kubernetes", + "nodename": "__KUBERNETES_NODE_NAME__", + "mtu": __CNI_MTU__, + "ipam": { + "type": "calico-ipam" + }, + "policy": { + "type": "k8s" + }, + "kubernetes": { + "kubeconfig": "__KUBECONFIG_FILEPATH__" + } + }, + { + "type": "portmap", + "snat": true, + "capabilities": {"portMappings": true} + }, + { + "type": "bandwidth", + "capabilities": {"bandwidth": true} + } + ] + } + +--- +# Source: calico/templates/kdd-crds.yaml + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: bgpconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPConfiguration + listKind: BGPConfigurationList + plural: bgpconfigurations + singular: bgpconfiguration + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: BGPConfiguration contains the configuration for any BGP routing. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BGPConfigurationSpec contains the values of the BGP configuration. + properties: + asNumber: + description: 'ASNumber is the default AS number used by a node. [Default: + 64512]' + format: int32 + type: integer + communities: + description: Communities is a list of BGP community values and their + arbitrary names for tagging routes. + items: + description: Community contains standard or large community value + and its name. + properties: + name: + description: Name given to community value. + type: string + value: + description: Value must be of format `aa:nn` or `aa:nn:mm`. + For standard community use `aa:nn` format, where `aa` and + `nn` are 16 bit number. For large community use `aa:nn:mm` + format, where `aa`, `nn` and `mm` are 32 bit number. Where, + `aa` is an AS Number, `nn` and `mm` are per-AS identifier. + pattern: ^(\d+):(\d+)$|^(\d+):(\d+):(\d+)$ + type: string + type: object + type: array + listenPort: + description: ListenPort is the port where BGP protocol should listen. + Defaults to 179 + maximum: 65535 + minimum: 1 + type: integer + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: INFO]' + type: string + nodeToNodeMeshEnabled: + description: 'NodeToNodeMeshEnabled sets whether full node to node + BGP mesh is enabled. [Default: true]' + type: boolean + prefixAdvertisements: + description: PrefixAdvertisements contains per-prefix advertisement + configuration. + items: + description: PrefixAdvertisement configures advertisement properties + for the specified CIDR. + properties: + cidr: + description: CIDR for which properties should be advertised. + type: string + communities: + description: Communities can be list of either community names + already defined in `Specs.Communities` or community value + of format `aa:nn` or `aa:nn:mm`. For standard community use + `aa:nn` format, where `aa` and `nn` are 16 bit number. For + large community use `aa:nn:mm` format, where `aa`, `nn` and + `mm` are 32 bit number. Where,`aa` is an AS Number, `nn` and + `mm` are per-AS identifier. + items: + type: string + type: array + type: object + type: array + serviceClusterIPs: + description: ServiceClusterIPs are the CIDR blocks from which service + cluster IPs are allocated. If specified, Calico will advertise these + blocks, as well as any cluster IPs within them. + items: + description: ServiceClusterIPBlock represents a single allowed ClusterIP + CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceExternalIPs: + description: ServiceExternalIPs are the CIDR blocks for Kubernetes + Service External IPs. Kubernetes Service ExternalIPs will only be + advertised if they are within one of these blocks. + items: + description: ServiceExternalIPBlock represents a single allowed + External IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceLoadBalancerIPs: + description: ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes + Service LoadBalancer IPs. Kubernetes Service status.LoadBalancer.Ingress + IPs will only be advertised if they are within one of these blocks. + items: + description: ServiceLoadBalancerIPBlock represents a single allowed + LoadBalancer IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: bgppeers.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BGPPeerSpec contains the specification for a BGPPeer resource. + properties: + asNumber: + description: The AS Number of the peer. + format: int32 + type: integer + keepOriginalNextHop: + description: Option to keep the original nexthop field when routes + are sent to a BGP Peer. Setting "true" configures the selected BGP + Peers node to use the "next hop keep;" instead of "next hop self;"(default) + in the specific branch of the Node on "bird.cfg". + type: boolean + node: + description: The node name identifying the Calico node instance that + is targeted by this peer. If this is not set, and no nodeSelector + is specified, then this BGP peer selects all nodes in the cluster. + type: string + nodeSelector: + description: Selector for the nodes that should have this peering. When + this is set, the Node field must be empty. + type: string + password: + description: Optional BGP password for the peerings generated by this + BGPPeer resource. + properties: + secretKeyRef: + description: Selects a key of a secret in the node pod's namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + type: object + peerIP: + description: The IP address of the peer followed by an optional port + number to peer with. If port number is given, format should be `[]:port` + or `:` for IPv4. If optional port number is not set, + and this peer IP and ASNumber belongs to a calico/node with ListenPort + set in BGPConfiguration, then we use that port to peer. + type: string + peerSelector: + description: Selector for the remote nodes to peer with. When this + is set, the PeerIP and ASNumber fields must be empty. For each + peering between the local node and selected remote nodes, we configure + an IPv4 peering if both ends have NodeBGPSpec.IPv4Address specified, + and an IPv6 peering if both ends have NodeBGPSpec.IPv6Address specified. The + remote AS number comes from the remote node's NodeBGPSpec.ASNumber, + or the global default if that is not set. + type: string + sourceAddress: + description: Specifies whether and how to configure a source address + for the peerings generated by this BGPPeer resource. Default value + "UseNodeIP" means to configure the node IP as the source address. "None" + means not to configure a source address. + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: blockaffinities.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BlockAffinity + listKind: BlockAffinityList + plural: blockaffinities + singular: blockaffinity + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BlockAffinitySpec contains the specification for a BlockAffinity + resource. + properties: + cidr: + type: string + deleted: + description: Deleted indicates that this block affinity is being deleted. + This field is a string for compatibility with older releases that + mistakenly treat this field as a string. + type: string + node: + type: string + state: + type: string + required: + - cidr + - deleted + - node + - state + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterinformations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: ClusterInformation + listKind: ClusterInformationList + plural: clusterinformations + singular: clusterinformation + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ClusterInformation contains the cluster specific information. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterInformationSpec contains the values of describing + the cluster. + properties: + calicoVersion: + description: CalicoVersion is the version of Calico that the cluster + is running + type: string + clusterGUID: + description: ClusterGUID is the GUID of the cluster + type: string + clusterType: + description: ClusterType describes the type of the cluster + type: string + datastoreReady: + description: DatastoreReady is used during significant datastore migrations + to signal to components such as Felix that it should wait before + accessing the datastore. + type: boolean + variant: + description: Variant declares which variant of Calico should be active. + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: felixconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: FelixConfiguration + listKind: FelixConfigurationList + plural: felixconfigurations + singular: felixconfiguration + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Felix Configuration contains the configuration for Felix. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: FelixConfigurationSpec contains the values of the Felix configuration. + properties: + allowIPIPPacketsFromWorkloads: + description: 'AllowIPIPPacketsFromWorkloads controls whether Felix + will add a rule to drop IPIP encapsulated traffic from workloads + [Default: false]' + type: boolean + allowVXLANPacketsFromWorkloads: + description: 'AllowVXLANPacketsFromWorkloads controls whether Felix + will add a rule to drop VXLAN encapsulated traffic from workloads + [Default: false]' + type: boolean + awsSrcDstCheck: + description: 'Set source-destination-check on AWS EC2 instances. Accepted + value must be one of "DoNothing", "Enabled" or "Disabled". [Default: + DoNothing]' + enum: + - DoNothing + - Enable + - Disable + type: string + bpfConnectTimeLoadBalancingEnabled: + description: 'BPFConnectTimeLoadBalancingEnabled when in BPF mode, + controls whether Felix installs the connection-time load balancer. The + connect-time load balancer is required for the host to be able to + reach Kubernetes services and it improves the performance of pod-to-service + connections. The only reason to disable it is for debugging purposes. [Default: + true]' + type: boolean + bpfDataIfacePattern: + description: BPFDataIfacePattern is a regular expression that controls + which interfaces Felix should attach BPF programs to in order to + catch traffic to/from the network. This needs to match the interfaces + that Calico workload traffic flows over as well as any interfaces + that handle incoming traffic to nodeports and services from outside + the cluster. It should not match the workload interfaces (usually + named cali...). + type: string + bpfDisableUnprivileged: + description: 'BPFDisableUnprivileged, if enabled, Felix sets the kernel.unprivileged_bpf_disabled + sysctl to disable unprivileged use of BPF. This ensures that unprivileged + users cannot access Calico''s BPF maps and cannot insert their own + BPF programs to interfere with Calico''s. [Default: true]' + type: boolean + bpfEnabled: + description: 'BPFEnabled, if enabled Felix will use the BPF dataplane. + [Default: false]' + type: boolean + bpfExternalServiceMode: + description: 'BPFExternalServiceMode in BPF mode, controls how connections + from outside the cluster to services (node ports and cluster IPs) + are forwarded to remote workloads. If set to "Tunnel" then both + request and response traffic is tunneled to the remote node. If + set to "DSR", the request traffic is tunneled but the response traffic + is sent directly from the remote node. In "DSR" mode, the remote + node appears to use the IP of the ingress node; this requires a + permissive L2 network. [Default: Tunnel]' + type: string + bpfKubeProxyEndpointSlicesEnabled: + description: BPFKubeProxyEndpointSlicesEnabled in BPF mode, controls + whether Felix's embedded kube-proxy accepts EndpointSlices or not. + type: boolean + bpfKubeProxyIptablesCleanupEnabled: + description: 'BPFKubeProxyIptablesCleanupEnabled, if enabled in BPF + mode, Felix will proactively clean up the upstream Kubernetes kube-proxy''s + iptables chains. Should only be enabled if kube-proxy is not running. [Default: + true]' + type: boolean + bpfKubeProxyMinSyncPeriod: + description: 'BPFKubeProxyMinSyncPeriod, in BPF mode, controls the + minimum time between updates to the dataplane for Felix''s embedded + kube-proxy. Lower values give reduced set-up latency. Higher values + reduce Felix CPU usage by batching up more work. [Default: 1s]' + type: string + bpfLogLevel: + description: 'BPFLogLevel controls the log level of the BPF programs + when in BPF dataplane mode. One of "Off", "Info", or "Debug". The + logs are emitted to the BPF trace pipe, accessible with the command + `tc exec bpf debug`. [Default: Off].' + type: string + chainInsertMode: + description: 'ChainInsertMode controls whether Felix hooks the kernel''s + top-level iptables chains by inserting a rule at the top of the + chain or by appending a rule at the bottom. insert is the safe default + since it prevents Calico''s rules from being bypassed. If you switch + to append mode, be sure that the other rules in the chains signal + acceptance by falling through to the Calico rules, otherwise the + Calico policy will be bypassed. [Default: insert]' + type: string + dataplaneDriver: + type: string + debugDisableLogDropping: + type: boolean + debugMemoryProfilePath: + type: string + debugSimulateCalcGraphHangAfter: + type: string + debugSimulateDataplaneHangAfter: + type: string + defaultEndpointToHostAction: + description: 'DefaultEndpointToHostAction controls what happens to + traffic that goes from a workload endpoint to the host itself (after + the traffic hits the endpoint egress policy). By default Calico + blocks traffic from workload endpoints to the host itself with an + iptables "DROP" action. If you want to allow some or all traffic + from endpoint to host, set this parameter to RETURN or ACCEPT. Use + RETURN if you have your own rules in the iptables "INPUT" chain; + Calico will insert its rules at the top of that chain, then "RETURN" + packets to the "INPUT" chain once it has completed processing workload + endpoint egress policy. Use ACCEPT to unconditionally accept packets + from workloads after processing workload endpoint egress policy. + [Default: Drop]' + type: string + deviceRouteProtocol: + description: This defines the route protocol added to programmed device + routes, by default this will be RTPROT_BOOT when left blank. + type: integer + deviceRouteSourceAddress: + description: This is the source address to use on programmed device + routes. By default the source address is left blank, leaving the + kernel to choose the source address used. + type: string + disableConntrackInvalidCheck: + type: boolean + endpointReportingDelay: + type: string + endpointReportingEnabled: + type: boolean + externalNodesList: + description: ExternalNodesCIDRList is a list of CIDR's of external-non-calico-nodes + which may source tunnel traffic and have the tunneled traffic be + accepted at calico nodes. + items: + type: string + type: array + failsafeInboundHostPorts: + description: 'FailsafeInboundHostPorts is a comma-delimited list of + UDP/TCP ports that Felix will allow incoming traffic to host endpoints + on irrespective of the security policy. This is useful to avoid + accidentally cutting off a host with incorrect configuration. Each + port should be specified as tcp: or udp:. + For back-compatibility, if the protocol is not specified, it defaults + to "tcp". To disable all inbound host ports, use the value none. + The default value allows ssh access and DHCP. [Default: tcp:22, + udp:68, tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, tcp:6667]' + items: + description: ProtoPort is combination of protocol and port, both + must be specified. + properties: + port: + type: integer + protocol: + type: string + required: + - port + - protocol + type: object + type: array + failsafeOutboundHostPorts: + description: 'FailsafeOutboundHostPorts is a comma-delimited list + of UDP/TCP ports that Felix will allow outgoing traffic from host + endpoints to irrespective of the security policy. This is useful + to avoid accidentally cutting off a host with incorrect configuration. + Each port should be specified as tcp: or udp:. + For back-compatibility, if the protocol is not specified, it defaults + to "tcp". To disable all outbound host ports, use the value none. + The default value opens etcd''s standard ports to ensure that Felix + does not get cut off from etcd as well as allowing DHCP and DNS. + [Default: tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, tcp:6667, + udp:53, udp:67]' + items: + description: ProtoPort is combination of protocol and port, both + must be specified. + properties: + port: + type: integer + protocol: + type: string + required: + - port + - protocol + type: object + type: array + featureDetectOverride: + description: FeatureDetectOverride is used to override the feature + detection. Values are specified in a comma separated list with no + spaces, example; "SNATFullyRandom=true,MASQFullyRandom=false,RestoreSupportsLock=". + "true" or "false" will force the feature, empty or omitted values + are auto-detected. + type: string + genericXDPEnabled: + description: 'GenericXDPEnabled enables Generic XDP so network cards + that don''t support XDP offload or driver modes can use XDP. This + is not recommended since it doesn''t provide better performance + than iptables. [Default: false]' + type: boolean + healthEnabled: + type: boolean + healthHost: + type: string + healthPort: + type: integer + interfaceExclude: + description: 'InterfaceExclude is a comma-separated list of interfaces + that Felix should exclude when monitoring for host endpoints. The + default value ensures that Felix ignores Kubernetes'' IPVS dummy + interface, which is used internally by kube-proxy. If you want to + exclude multiple interface names using a single value, the list + supports regular expressions. For regular expressions you must wrap + the value with ''/''. For example having values ''/^kube/,veth1'' + will exclude all interfaces that begin with ''kube'' and also the + interface ''veth1''. [Default: kube-ipvs0]' + type: string + interfacePrefix: + description: 'InterfacePrefix is the interface name prefix that identifies + workload endpoints and so distinguishes them from host endpoint + interfaces. Note: in environments other than bare metal, the orchestrators + configure this appropriately. For example our Kubernetes and Docker + integrations set the ''cali'' value, and our OpenStack integration + sets the ''tap'' value. [Default: cali]' + type: string + interfaceRefreshInterval: + description: InterfaceRefreshInterval is the period at which Felix + rescans local interfaces to verify their state. The rescan can be + disabled by setting the interval to 0. + type: string + ipipEnabled: + type: boolean + ipipMTU: + description: 'IPIPMTU is the MTU to set on the tunnel device. See + Configuring MTU [Default: 1440]' + type: integer + ipsetsRefreshInterval: + description: 'IpsetsRefreshInterval is the period at which Felix re-checks + all iptables state to ensure that no other process has accidentally + broken Calico''s rules. Set to 0 to disable iptables refresh. [Default: + 90s]' + type: string + iptablesBackend: + description: IptablesBackend specifies which backend of iptables will + be used. The default is legacy. + type: string + iptablesFilterAllowAction: + type: string + iptablesLockFilePath: + description: 'IptablesLockFilePath is the location of the iptables + lock file. You may need to change this if the lock file is not in + its standard location (for example if you have mapped it into Felix''s + container at a different path). [Default: /run/xtables.lock]' + type: string + iptablesLockProbeInterval: + description: 'IptablesLockProbeInterval is the time that Felix will + wait between attempts to acquire the iptables lock if it is not + available. Lower values make Felix more responsive when the lock + is contended, but use more CPU. [Default: 50ms]' + type: string + iptablesLockTimeout: + description: 'IptablesLockTimeout is the time that Felix will wait + for the iptables lock, or 0, to disable. To use this feature, Felix + must share the iptables lock file with all other processes that + also take the lock. When running Felix inside a container, this + requires the /run directory of the host to be mounted into the calico/node + or calico/felix container. [Default: 0s disabled]' + type: string + iptablesMangleAllowAction: + type: string + iptablesMarkMask: + description: 'IptablesMarkMask is the mask that Felix selects its + IPTables Mark bits from. Should be a 32 bit hexadecimal number with + at least 8 bits set, none of which clash with any other mark bits + in use on the system. [Default: 0xff000000]' + format: int32 + type: integer + iptablesNATOutgoingInterfaceFilter: + type: string + iptablesPostWriteCheckInterval: + description: 'IptablesPostWriteCheckInterval is the period after Felix + has done a write to the dataplane that it schedules an extra read + back in order to check the write was not clobbered by another process. + This should only occur if another application on the system doesn''t + respect the iptables lock. [Default: 1s]' + type: string + iptablesRefreshInterval: + description: 'IptablesRefreshInterval is the period at which Felix + re-checks the IP sets in the dataplane to ensure that no other process + has accidentally broken Calico''s rules. Set to 0 to disable IP + sets refresh. Note: the default for this value is lower than the + other refresh intervals as a workaround for a Linux kernel bug that + was fixed in kernel version 4.11. If you are using v4.11 or greater + you may want to set this to, a higher value to reduce Felix CPU + usage. [Default: 10s]' + type: string + ipv6Support: + type: boolean + kubeNodePortRanges: + description: 'KubeNodePortRanges holds list of port ranges used for + service node ports. Only used if felix detects kube-proxy running + in ipvs mode. Felix uses these ranges to separate host and workload + traffic. [Default: 30000:32767].' + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + logFilePath: + description: 'LogFilePath is the full path to the Felix log. Set to + none to disable file logging. [Default: /var/log/calico/felix.log]' + type: string + logPrefix: + description: 'LogPrefix is the log prefix that Felix uses when rendering + LOG rules. [Default: calico-packet]' + type: string + logSeverityFile: + description: 'LogSeverityFile is the log severity above which logs + are sent to the log file. [Default: Info]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + type: string + logSeveritySys: + description: 'LogSeveritySys is the log severity above which logs + are sent to the syslog. Set to None for no logging to syslog. [Default: + Info]' + type: string + maxIpsetSize: + type: integer + metadataAddr: + description: 'MetadataAddr is the IP address or domain name of the + server that can answer VM queries for cloud-init metadata. In OpenStack, + this corresponds to the machine running nova-api (or in Ubuntu, + nova-api-metadata). A value of none (case insensitive) means that + Felix should not set up any NAT rule for the metadata path. [Default: + 127.0.0.1]' + type: string + metadataPort: + description: 'MetadataPort is the port of the metadata server. This, + combined with global.MetadataAddr (if not ''None''), is used to + set up a NAT rule, from 169.254.169.254:80 to MetadataAddr:MetadataPort. + In most cases this should not need to be changed [Default: 8775].' + type: integer + mtuIfacePattern: + description: MTUIfacePattern is a regular expression that controls + which interfaces Felix should scan in order to calculate the host's + MTU. This should not match workload interfaces (usually named cali...). + type: string + natOutgoingAddress: + description: NATOutgoingAddress specifies an address to use when performing + source NAT for traffic in a natOutgoing pool that is leaving the + network. By default the address used is an address on the interface + the traffic is leaving on (ie it uses the iptables MASQUERADE target) + type: string + natPortRange: + anyOf: + - type: integer + - type: string + description: NATPortRange specifies the range of ports that is used + for port mapping when doing outgoing NAT. When unset the default + behavior of the network stack is used. + pattern: ^.* + x-kubernetes-int-or-string: true + netlinkTimeout: + type: string + openstackRegion: + description: 'OpenstackRegion is the name of the region that a particular + Felix belongs to. In a multi-region Calico/OpenStack deployment, + this must be configured somehow for each Felix (here in the datamodel, + or in felix.cfg or the environment on each compute node), and must + match the [calico] openstack_region value configured in neutron.conf + on each node. [Default: Empty]' + type: string + policySyncPathPrefix: + description: 'PolicySyncPathPrefix is used to by Felix to communicate + policy changes to external services, like Application layer policy. + [Default: Empty]' + type: string + prometheusGoMetricsEnabled: + description: 'PrometheusGoMetricsEnabled disables Go runtime metrics + collection, which the Prometheus client does by default, when set + to false. This reduces the number of metrics reported, reducing + Prometheus load. [Default: true]' + type: boolean + prometheusMetricsEnabled: + description: 'PrometheusMetricsEnabled enables the Prometheus metrics + server in Felix if set to true. [Default: false]' + type: boolean + prometheusMetricsHost: + description: 'PrometheusMetricsHost is the host that the Prometheus + metrics server should bind to. [Default: empty]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. [Default: 9091]' + type: integer + prometheusProcessMetricsEnabled: + description: 'PrometheusProcessMetricsEnabled disables process metrics + collection, which the Prometheus client does by default, when set + to false. This reduces the number of metrics reported, reducing + Prometheus load. [Default: true]' + type: boolean + removeExternalRoutes: + description: Whether or not to remove device routes that have not + been programmed by Felix. Disabling this will allow external applications + to also add device routes. This is enabled by default which means + we will remove externally added routes. + type: boolean + reportingInterval: + description: 'ReportingInterval is the interval at which Felix reports + its status into the datastore or 0 to disable. Must be non-zero + in OpenStack deployments. [Default: 30s]' + type: string + reportingTTL: + description: 'ReportingTTL is the time-to-live setting for process-wide + status reports. [Default: 90s]' + type: string + routeRefreshInterval: + description: 'RouteRefreshInterval is the period at which Felix re-checks + the routes in the dataplane to ensure that no other process has + accidentally broken Calico''s rules. Set to 0 to disable route refresh. + [Default: 90s]' + type: string + routeSource: + description: 'RouteSource configures where Felix gets its routing + information. - WorkloadIPs: use workload endpoints to construct + routes. - CalicoIPAM: the default - use IPAM data to construct routes.' + type: string + routeTableRange: + description: Calico programs additional Linux route tables for various + purposes. RouteTableRange specifies the indices of the route tables + that Calico should use. + properties: + max: + type: integer + min: + type: integer + required: + - max + - min + type: object + serviceLoopPrevention: + description: 'When service IP advertisement is enabled, prevent routing + loops to service IPs that are not in use, by dropping or rejecting + packets that do not get DNAT''d by kube-proxy. Unless set to "Disabled", + in which case such routing loops continue to be allowed. [Default: + Drop]' + type: string + sidecarAccelerationEnabled: + description: 'SidecarAccelerationEnabled enables experimental sidecar + acceleration [Default: false]' + type: boolean + usageReportingEnabled: + description: 'UsageReportingEnabled reports anonymous Calico version + number and cluster size to projectcalico.org. Logs warnings returned + by the usage server. For example, if a significant security vulnerability + has been discovered in the version of Calico being used. [Default: + true]' + type: boolean + usageReportingInitialDelay: + description: 'UsageReportingInitialDelay controls the minimum delay + before Felix makes a report. [Default: 300s]' + type: string + usageReportingInterval: + description: 'UsageReportingInterval controls the interval at which + Felix makes reports. [Default: 86400s]' + type: string + useInternalDataplaneDriver: + type: boolean + vxlanEnabled: + type: boolean + vxlanMTU: + description: 'VXLANMTU is the MTU to set on the tunnel device. See + Configuring MTU [Default: 1440]' + type: integer + vxlanPort: + type: integer + vxlanVNI: + type: integer + wireguardEnabled: + description: 'WireguardEnabled controls whether Wireguard is enabled. + [Default: false]' + type: boolean + wireguardInterfaceName: + description: 'WireguardInterfaceName specifies the name to use for + the Wireguard interface. [Default: wg.calico]' + type: string + wireguardListeningPort: + description: 'WireguardListeningPort controls the listening port used + by Wireguard. [Default: 51820]' + type: integer + wireguardMTU: + description: 'WireguardMTU controls the MTU on the Wireguard interface. + See Configuring MTU [Default: 1420]' + type: integer + wireguardRoutingRulePriority: + description: 'WireguardRoutingRulePriority controls the priority value + to use for the Wireguard routing rule. [Default: 99]' + type: integer + xdpEnabled: + description: 'XDPEnabled enables XDP acceleration for suitable untracked + incoming deny rules. [Default: true]' + type: boolean + xdpRefreshInterval: + description: 'XDPRefreshInterval is the period at which Felix re-checks + all XDP state to ensure that no other process has accidentally broken + Calico''s BPF maps or attached programs. Set to 0 to disable XDP + refresh. [Default: 90s]' + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: globalnetworkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkPolicy + listKind: GlobalNetworkPolicyList + plural: globalnetworkpolicies + singular: globalnetworkpolicy + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + applyOnForward: + description: ApplyOnForward indicates to apply the rules in this policy + on forward traffic. + type: boolean + doNotTrack: + description: DoNotTrack indicates whether packets matched by the rules + in this policy should go through the data plane's connection tracking, + such as Linux conntrack. If True, the rules in this policy are + applied before any data plane connection tracking, and packets allowed + by this policy are marked as not to be tracked. + type: boolean + egress: + description: The ordered set of egress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: The ordered set of ingress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + required: + - action + type: object + type: array + namespaceSelector: + description: NamespaceSelector is an optional field for an expression + used to select a pod based on namespaces. + type: string + order: + description: Order is an optional field that specifies the order in + which the policy is applied. Policies with higher "order" are applied + after those with lower order. If the order is omitted, it may be + considered to be "infinite" - i.e. the policy will be applied last. Policies + with identical order will be applied in alphanumerical order based + on the Policy "Name". + type: number + preDNAT: + description: PreDNAT indicates to apply the rules in this policy before + any DNAT. + type: boolean + selector: + description: "The selector is an expression used to pick pick out + the endpoints that the policy should be applied to. \n Selector + expressions follow this syntax: \n \tlabel == \"string_literal\" + \ -> comparison, e.g. my_label == \"foo bar\" \tlabel != \"string_literal\" + \ -> not equal; also matches if label is not present \tlabel in + { \"a\", \"b\", \"c\", ... } -> true if the value of label X is + one of \"a\", \"b\", \"c\" \tlabel not in { \"a\", \"b\", \"c\", + ... } -> true if the value of label X is not one of \"a\", \"b\", + \"c\" \thas(label_name) -> True if that label is present \t! expr + -> negation of expr \texpr && expr -> Short-circuit and \texpr + || expr -> Short-circuit or \t( expr ) -> parens for grouping \tall() + or the empty selector -> matches all endpoints. \n Label names are + allowed to contain alphanumerics, -, _ and /. String literals are + more permissive but they do not support escape characters. \n Examples + (with made-up labels): \n \ttype == \"webserver\" && deployment + == \"prod\" \ttype in {\"frontend\", \"backend\"} \tdeployment != + \"dev\" \t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + types: + description: "Types indicates whether this policy applies to ingress, + or to egress, or to both. When not explicitly specified (and so + the value on creation is empty or nil), Calico defaults Types according + to what Ingress and Egress rules are present in the policy. The + default is: \n - [ PolicyTypeIngress ], if there are no Egress rules + (including the case where there are also no Ingress rules) \n + - [ PolicyTypeEgress ], if there are Egress rules but no Ingress + rules \n - [ PolicyTypeIngress, PolicyTypeEgress ], if there are + both Ingress and Egress rules. \n When the policy is read back again, + Types will always be one of these values, never empty or nil." + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: globalnetworksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkSet + listKind: GlobalNetworkSetList + plural: globalnetworksets + singular: globalnetworkset + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: GlobalNetworkSet contains a set of arbitrary IP sub-networks/CIDRs + that share labels to allow rules to refer to them via selectors. The labels + of GlobalNetworkSet are not namespaced. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: GlobalNetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: hostendpoints.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: HostEndpoint + listKind: HostEndpointList + plural: hostendpoints + singular: hostendpoint + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HostEndpointSpec contains the specification for a HostEndpoint + resource. + properties: + expectedIPs: + description: "The expected IP addresses (IPv4 and IPv6) of the endpoint. + If \"InterfaceName\" is not present, Calico will look for an interface + matching any of the IPs in the list and apply policy to that. Note: + \tWhen using the selector match criteria in an ingress or egress + security Policy \tor Profile, Calico converts the selector into + a set of IP addresses. For host \tendpoints, the ExpectedIPs field + is used for that purpose. (If only the interface \tname is specified, + Calico does not learn the IPs of the interface for use in match + \tcriteria.)" + items: + type: string + type: array + interfaceName: + description: "Either \"*\", or the name of a specific Linux interface + to apply policy to; or empty. \"*\" indicates that this HostEndpoint + governs all traffic to, from or through the default network namespace + of the host named by the \"Node\" field; entering and leaving that + namespace via any interface, including those from/to non-host-networked + local workloads. \n If InterfaceName is not \"*\", this HostEndpoint + only governs traffic that enters or leaves the host through the + specific interface named by InterfaceName, or - when InterfaceName + is empty - through the specific interface that has one of the IPs + in ExpectedIPs. Therefore, when InterfaceName is empty, at least + one expected IP must be specified. Only external interfaces (such + as \"eth0\") are supported here; it isn't possible for a HostEndpoint + to protect traffic through a specific local workload interface. + \n Note: Only some kinds of policy are implemented for \"*\" HostEndpoints; + initially just pre-DNAT policy. Please check Calico documentation + for the latest position." + type: string + node: + description: The node name identifying the Calico node instance. + type: string + ports: + description: Ports contains the endpoint's named ports, which may + be referenced in security policy rules. + items: + properties: + name: + type: string + port: + type: integer + protocol: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + required: + - name + - port + - protocol + type: object + type: array + profiles: + description: A list of identifiers of security Profile objects that + apply to this endpoint. Each profile is applied in the order that + they appear in this list. Profile rules are applied after the selector-based + security policy. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamblocks.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMBlock + listKind: IPAMBlockList + plural: ipamblocks + singular: ipamblock + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMBlockSpec contains the specification for an IPAMBlock + resource. + properties: + affinity: + type: string + allocations: + items: + type: integer + # TODO: This nullable is manually added in. We should update controller-gen + # to handle []*int properly itself. + nullable: true + type: array + attributes: + items: + properties: + handle_id: + type: string + secondary: + additionalProperties: + type: string + type: object + type: object + type: array + cidr: + type: string + deleted: + type: boolean + strictAffinity: + type: boolean + unallocated: + items: + type: integer + type: array + required: + - allocations + - attributes + - cidr + - strictAffinity + - unallocated + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamconfigs.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMConfig + listKind: IPAMConfigList + plural: ipamconfigs + singular: ipamconfig + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMConfigSpec contains the specification for an IPAMConfig + resource. + properties: + autoAllocateBlocks: + type: boolean + maxBlocksPerHost: + description: MaxBlocksPerHost, if non-zero, is the max number of blocks + that can be affine to each host. + type: integer + strictAffinity: + type: boolean + required: + - autoAllocateBlocks + - strictAffinity + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamhandles.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMHandle + listKind: IPAMHandleList + plural: ipamhandles + singular: ipamhandle + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMHandleSpec contains the specification for an IPAMHandle + resource. + properties: + block: + additionalProperties: + type: integer + type: object + deleted: + type: boolean + handleID: + type: string + required: + - block + - handleID + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ippools.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPPool + listKind: IPPoolList + plural: ippools + singular: ippool + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPPoolSpec contains the specification for an IPPool resource. + properties: + blockSize: + description: The block size to use for IP address assignments from + this pool. Defaults to 26 for IPv4 and 112 for IPv6. + type: integer + cidr: + description: The pool CIDR. + type: string + disabled: + description: When disabled is true, Calico IPAM will not assign addresses + from this pool. + type: boolean + ipip: + description: 'Deprecated: this field is only used for APIv1 backwards + compatibility. Setting this field is not allowed, this field is + for internal use only.' + properties: + enabled: + description: When enabled is true, ipip tunneling will be used + to deliver packets to destinations within this pool. + type: boolean + mode: + description: The IPIP mode. This can be one of "always" or "cross-subnet". A + mode of "always" will also use IPIP tunneling for routing to + destination IP addresses within this pool. A mode of "cross-subnet" + will only use IPIP tunneling when the destination node is on + a different subnet to the originating node. The default value + (if not specified) is "always". + type: string + type: object + ipipMode: + description: Contains configuration for IPIP tunneling for this pool. + If not specified, then this is defaulted to "Never" (i.e. IPIP tunneling + is disabled). + type: string + nat-outgoing: + description: 'Deprecated: this field is only used for APIv1 backwards + compatibility. Setting this field is not allowed, this field is + for internal use only.' + type: boolean + natOutgoing: + description: When nat-outgoing is true, packets sent from Calico networked + containers in this pool to destinations outside of this pool will + be masqueraded. + type: boolean + nodeSelector: + description: Allows IPPool to allocate for a specific node by label + selector. + type: string + vxlanMode: + description: Contains configuration for VXLAN tunneling for this pool. + If not specified, then this is defaulted to "Never" (i.e. VXLAN + tunneling is disabled). + type: string + required: + - cidr + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kubecontrollersconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: KubeControllersConfiguration + listKind: KubeControllersConfigurationList + plural: kubecontrollersconfigurations + singular: kubecontrollersconfiguration + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeControllersConfigurationSpec contains the values of the + Kubernetes controllers configuration. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + namespace: + description: Namespace enables and configures the namespace controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host endpoints. + Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation of + host endpoints for every node. [Default: Disabled]' + type: string + type: object + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + type: object + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: 9094]' + type: integer + required: + - controllers + type: object + status: + description: KubeControllersConfigurationStatus represents the status + of the configuration. It's useful for admins to be able to see the actual + config that was applied, which can be modified by environment variables + on the kube-controllers process. + properties: + environmentVars: + additionalProperties: + type: string + description: EnvironmentVars contains the environment variables on + the kube-controllers that influenced the RunningConfig. + type: object + runningConfig: + description: RunningConfig contains the effective config that is running + in the kube-controllers pod, after merging the API resource with + any environment variables. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + namespace: + description: Namespace enables and configures the namespace + controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host + endpoints. Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation + of host endpoints for every node. [Default: Disabled]' + type: string + type: object + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + type: object + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which + logs are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: + 9094]' + type: integer + required: + - controllers + type: object + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkPolicy + listKind: NetworkPolicyList + plural: networkpolicies + singular: networkpolicy + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + egress: + description: The ordered set of egress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: The ordered set of ingress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and Selector are defined on the same rule, then only workload + endpoints that are matched by both selectors will be selected + by the rule. \n For NetworkPolicy, an empty NamespaceSelector + implies that the Selector is limited to selecting only + workload endpoints in the same namespace as the NetworkPolicy. + \n For NetworkPolicy, `global()` NamespaceSelector implies + that the Selector is limited to selecting only GlobalNetworkSet + or HostEndpoint. \n For GlobalNetworkPolicy, an empty + NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + type: object + required: + - action + type: object + type: array + order: + description: Order is an optional field that specifies the order in + which the policy is applied. Policies with higher "order" are applied + after those with lower order. If the order is omitted, it may be + considered to be "infinite" - i.e. the policy will be applied last. Policies + with identical order will be applied in alphanumerical order based + on the Policy "Name". + type: number + selector: + description: "The selector is an expression used to pick pick out + the endpoints that the policy should be applied to. \n Selector + expressions follow this syntax: \n \tlabel == \"string_literal\" + \ -> comparison, e.g. my_label == \"foo bar\" \tlabel != \"string_literal\" + \ -> not equal; also matches if label is not present \tlabel in + { \"a\", \"b\", \"c\", ... } -> true if the value of label X is + one of \"a\", \"b\", \"c\" \tlabel not in { \"a\", \"b\", \"c\", + ... } -> true if the value of label X is not one of \"a\", \"b\", + \"c\" \thas(label_name) -> True if that label is present \t! expr + -> negation of expr \texpr && expr -> Short-circuit and \texpr + || expr -> Short-circuit or \t( expr ) -> parens for grouping \tall() + or the empty selector -> matches all endpoints. \n Label names are + allowed to contain alphanumerics, -, _ and /. String literals are + more permissive but they do not support escape characters. \n Examples + (with made-up labels): \n \ttype == \"webserver\" && deployment + == \"prod\" \ttype in {\"frontend\", \"backend\"} \tdeployment != + \"dev\" \t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + types: + description: "Types indicates whether this policy applies to ingress, + or to egress, or to both. When not explicitly specified (and so + the value on creation is empty or nil), Calico defaults Types according + to what Ingress and Egress are present in the policy. The default + is: \n - [ PolicyTypeIngress ], if there are no Egress rules (including + the case where there are also no Ingress rules) \n - [ PolicyTypeEgress + ], if there are Egress rules but no Ingress rules \n - [ PolicyTypeIngress, + PolicyTypeEgress ], if there are both Ingress and Egress rules. + \n When the policy is read back again, Types will always be one + of these values, never empty or nil." + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkSet + listKind: NetworkSetList + plural: networksets + singular: networkset + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: NetworkSet is the Namespaced-equivalent of the GlobalNetworkSet. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +--- +# Source: calico/templates/calico-kube-controllers-rbac.yaml + +# Include a clusterrole for the kube-controllers component, +# and bind it to the calico-kube-controllers serviceaccount. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-kube-controllers +rules: + # Nodes are watched to monitor for deletions. + - apiGroups: [""] + resources: + - nodes + verbs: + - watch + - list + - get + # Pods are queried to check for existence. + - apiGroups: [""] + resources: + - pods + verbs: + - get + # IPAM resources are manipulated when nodes are deleted. + - apiGroups: ["crd.projectcalico.org"] + resources: + - ippools + verbs: + - list + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + - ipamblocks + - ipamhandles + verbs: + - get + - list + - create + - update + - delete + - watch + # kube-controllers manages hostendpoints. + - apiGroups: ["crd.projectcalico.org"] + resources: + - hostendpoints + verbs: + - get + - list + - create + - update + - delete + # Needs access to update clusterinformations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - clusterinformations + verbs: + - get + - create + - update + # KubeControllersConfiguration is where it gets its config + - apiGroups: ["crd.projectcalico.org"] + resources: + - kubecontrollersconfigurations + verbs: + # read its own config + - get + # create a default if none exists + - create + # update status + - update + # watch for changes + - watch +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-kube-controllers +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: calico-kube-controllers +subjects: + - kind: ServiceAccount + name: calico-kube-controllers + namespace: kube-system +--- + +--- +# Source: calico/templates/calico-node-rbac.yaml +# Include a clusterrole for the calico-node DaemonSet, +# and bind it to the calico-node serviceaccount. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-node +rules: + # The CNI plugin needs to get pods, nodes, and namespaces. + - apiGroups: [""] + resources: + - pods + - nodes + - namespaces + verbs: + - get + - apiGroups: [""] + resources: + - endpoints + - services + verbs: + # Used to discover service IPs for advertisement. + - watch + - list + # Used to discover Typhas. + - get + # Pod CIDR auto-detection on kubeadm needs access to config maps. + - apiGroups: [""] + resources: + - configmaps + verbs: + - get + - apiGroups: [""] + resources: + - nodes/status + verbs: + # Needed for clearing NodeNetworkUnavailable flag. + - patch + # Calico stores some configuration information in node annotations. + - update + # Watch for changes to Kubernetes NetworkPolicies. + - apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: + - watch + - list + # Used by Calico for policy information. + - apiGroups: [""] + resources: + - pods + - namespaces + - serviceaccounts + verbs: + - list + - watch + # The CNI plugin patches pods/status. + - apiGroups: [""] + resources: + - pods/status + verbs: + - patch + # Calico monitors various CRDs for config. + - apiGroups: ["crd.projectcalico.org"] + resources: + - globalfelixconfigs + - felixconfigurations + - bgppeers + - globalbgpconfigs + - bgpconfigurations + - ippools + - ipamblocks + - globalnetworkpolicies + - globalnetworksets + - networkpolicies + - networksets + - clusterinformations + - hostendpoints + - blockaffinities + verbs: + - get + - list + - watch + # Calico must create and update some CRDs on startup. + - apiGroups: ["crd.projectcalico.org"] + resources: + - ippools + - felixconfigurations + - clusterinformations + verbs: + - create + - update + # Calico stores some configuration information on the node. + - apiGroups: [""] + resources: + - nodes + verbs: + - get + - list + - watch + # These permissions are only required for upgrade from v2.6, and can + # be removed after upgrade or on fresh installations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - bgpconfigurations + - bgppeers + verbs: + - create + - update + # These permissions are required for Calico CNI to perform IPAM allocations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + - ipamblocks + - ipamhandles + verbs: + - get + - list + - create + - update + - delete + - apiGroups: ["crd.projectcalico.org"] + resources: + - ipamconfigs + verbs: + - get + # Block affinities must also be watchable by confd for route aggregation. + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + verbs: + - watch + # The Calico IPAM migration needs to get daemonsets. These permissions can be + # removed if not upgrading from an installation using host-local IPAM. + - apiGroups: ["apps"] + resources: + - daemonsets + verbs: + - get + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: calico-node +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: calico-node +subjects: + - kind: ServiceAccount + name: calico-node + namespace: kube-system + +--- +# Source: calico/templates/calico-node.yaml +# This manifest installs the calico-node container, as well +# as the CNI plugins and network config on +# each master and worker node in a Kubernetes cluster. +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: calico-node + namespace: kube-system + labels: + k8s-app: calico-node +spec: + selector: + matchLabels: + k8s-app: calico-node + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + template: + metadata: + labels: + k8s-app: calico-node + spec: + nodeSelector: + kubernetes.io/os: linux + hostNetwork: true + tolerations: + # Make sure calico-node gets scheduled on all nodes. + - effect: NoSchedule + operator: Exists + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + serviceAccountName: calico-node + # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force + # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods. + terminationGracePeriodSeconds: 0 + priorityClassName: system-node-critical + initContainers: + # This container performs upgrade from host-local IPAM to calico-ipam. + # It can be deleted if this is a fresh installation, or if you have already + # upgraded to use calico-ipam. + - name: upgrade-ipam + image: docker.io/calico/cni:v3.18.1 + command: ["/opt/cni/bin/calico-ipam", "-upgrade"] + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: CALICO_NETWORKING_BACKEND + valueFrom: + configMapKeyRef: + name: calico-config + key: calico_backend + volumeMounts: + - mountPath: /var/lib/cni/networks + name: host-local-net-dir + - mountPath: /host/opt/cni/bin + name: cni-bin-dir + securityContext: + privileged: true + # This container installs the CNI binaries + # and CNI network config file on each node. + - name: install-cni + image: docker.io/calico/cni:v3.18.1 + command: ["/opt/cni/bin/install"] + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + # Name of the CNI config file to create. + - name: CNI_CONF_NAME + value: "10-calico.conflist" + # The CNI network config to install on each node. + - name: CNI_NETWORK_CONFIG + valueFrom: + configMapKeyRef: + name: calico-config + key: cni_network_config + # Set the hostname based on the k8s node name. + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # CNI MTU Config variable + - name: CNI_MTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Prevents the container from sleeping forever. + - name: SLEEP + value: "false" + volumeMounts: + - mountPath: /host/opt/cni/bin + name: cni-bin-dir + - mountPath: /host/etc/cni/net.d + name: cni-net-dir + securityContext: + privileged: true + # Adds a Flex Volume Driver that creates a per-pod Unix Domain Socket to allow Dikastes + # to communicate with Felix over the Policy Sync API. + - name: flexvol-driver + image: docker.io/calico/pod2daemon-flexvol:v3.18.1 + volumeMounts: + - name: flexvol-driver-host + mountPath: /host/driver + securityContext: + privileged: true + containers: + # Runs calico-node container on each Kubernetes node. This + # container programs network policy and routes on each + # host. + - name: calico-node + image: docker.io/calico/node:v3.18.1 + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + # Use Kubernetes API as the backing datastore. + - name: DATASTORE_TYPE + value: "kubernetes" + # Wait for the datastore. + - name: WAIT_FOR_DATASTORE + value: "true" + # Set based on the k8s node name. + - name: NODENAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # Choose the backend to use. + - name: CALICO_NETWORKING_BACKEND + valueFrom: + configMapKeyRef: + name: calico-config + key: calico_backend + # Cluster type to identify the deployment type + - name: CLUSTER_TYPE + value: "k8s,bgp" + # Auto-detect the BGP IP address. + - name: IP + value: "autodetect" + # Enable IPIP + - name: CALICO_IPV4POOL_IPIP + value: "Always" + # Enable or Disable VXLAN on the default IP pool. + - name: CALICO_IPV4POOL_VXLAN + value: "Never" + # Set MTU for tunnel device used if ipip is enabled + - name: FELIX_IPINIPMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Set MTU for the VXLAN tunnel device. + - name: FELIX_VXLANMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Set MTU for the Wireguard tunnel device. + - name: FELIX_WIREGUARDMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # The default IPv4 pool to create on startup if none exists. Pod IPs will be + # chosen from this range. Changing this value after installation will have + # no effect. This should fall within `--cluster-cidr`. + # - name: CALICO_IPV4POOL_CIDR + # value: "192.168.0.0/16" + # Disable file logging so `kubectl logs` works. + - name: CALICO_DISABLE_FILE_LOGGING + value: "true" + # Set Felix endpoint to host default action to ACCEPT. + - name: FELIX_DEFAULTENDPOINTTOHOSTACTION + value: "ACCEPT" + # Disable IPv6 on Kubernetes. + - name: FELIX_IPV6SUPPORT + value: "false" + # Set Felix logging to "info" + - name: FELIX_LOGSEVERITYSCREEN + value: "info" + - name: FELIX_HEALTHENABLED + value: "true" + securityContext: + privileged: true + resources: + requests: + cpu: 250m + livenessProbe: + exec: + command: + - /bin/calico-node + - -felix-live + - -bird-live + periodSeconds: 10 + initialDelaySeconds: 10 + failureThreshold: 6 + readinessProbe: + exec: + command: + - /bin/calico-node + - -felix-ready + - -bird-ready + periodSeconds: 10 + volumeMounts: + - mountPath: /lib/modules + name: lib-modules + readOnly: true + - mountPath: /run/xtables.lock + name: xtables-lock + readOnly: false + - mountPath: /var/run/calico + name: var-run-calico + readOnly: false + - mountPath: /var/lib/calico + name: var-lib-calico + readOnly: false + - name: policysync + mountPath: /var/run/nodeagent + # For eBPF mode, we need to be able to mount the BPF filesystem at /sys/fs/bpf so we mount in the + # parent directory. + - name: sysfs + mountPath: /sys/fs/ + # Bidirectional means that, if we mount the BPF filesystem at /sys/fs/bpf it will propagate to the host. + # If the host is known to mount that filesystem already then Bidirectional can be omitted. + mountPropagation: Bidirectional + - name: cni-log-dir + mountPath: /var/log/calico/cni + readOnly: true + volumes: + # Used by calico-node. + - name: lib-modules + hostPath: + path: /lib/modules + - name: var-run-calico + hostPath: + path: /var/run/calico + - name: var-lib-calico + hostPath: + path: /var/lib/calico + - name: xtables-lock + hostPath: + path: /run/xtables.lock + type: FileOrCreate + - name: sysfs + hostPath: + path: /sys/fs/ + type: DirectoryOrCreate + # Used to install CNI. + - name: cni-bin-dir + hostPath: + path: /opt/cni/bin + - name: cni-net-dir + hostPath: + path: /etc/cni/net.d + # Used to access CNI logs. + - name: cni-log-dir + hostPath: + path: /var/log/calico/cni + # Mount in the directory for host-local IPAM allocations. This is + # used when upgrading from host-local to calico-ipam, and can be removed + # if not using the upgrade-ipam init container. + - name: host-local-net-dir + hostPath: + path: /var/lib/cni/networks + # Used to create per-pod Unix Domain Sockets + - name: policysync + hostPath: + type: DirectoryOrCreate + path: /var/run/nodeagent + # Used to install Flex Volume Driver + - name: flexvol-driver-host + hostPath: + type: DirectoryOrCreate + path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: calico-node + namespace: kube-system + +--- +# Source: calico/templates/calico-kube-controllers.yaml +# See https://github.com/projectcalico/kube-controllers +apiVersion: apps/v1 +kind: Deployment +metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers +spec: + # The controllers can only have a single active instance. + replicas: 1 + selector: + matchLabels: + k8s-app: calico-kube-controllers + strategy: + type: Recreate + template: + metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers + spec: + nodeSelector: + kubernetes.io/os: linux + tolerations: + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - key: node-role.kubernetes.io/master + effect: NoSchedule + serviceAccountName: calico-kube-controllers + priorityClassName: system-cluster-critical + containers: + - name: calico-kube-controllers + image: docker.io/calico/kube-controllers:v3.18.1 + env: + # Choose which controllers to run. + - name: ENABLED_CONTROLLERS + value: node + - name: DATASTORE_TYPE + value: kubernetes + readinessProbe: + exec: + command: + - /usr/bin/check-status + - -r + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: calico-kube-controllers + namespace: kube-system + +--- + +# This manifest creates a Pod Disruption Budget for Controller to allow K8s Cluster Autoscaler to evict + +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers +spec: + maxUnavailable: 1 + selector: + matchLabels: + k8s-app: calico-kube-controllers + +--- +# Source: calico/templates/calico-etcd-secrets.yaml + +--- +# Source: calico/templates/calico-typha.yaml + +--- +# Source: calico/templates/configure-canal.yaml + + diff --git a/test/e2e/data/e2e_conf.yaml b/test/e2e/data/e2e_conf.yaml new file mode 100644 index 0000000000..b55829dffd --- /dev/null +++ b/test/e2e/data/e2e_conf.yaml @@ -0,0 +1,119 @@ +--- +# E2E test scenario using local dev images and manifests built from the source tree for following providers: +# - cluster-api +# - bootstrap kubeadm +# - control-plane kubeadm +# - openstack + +# To run tests, run the following from the root of this repository. +# `OPENSTACK_CLOUD=capo-e2e OPENSTACK_CLOUD_YAML_FILE=/tmp/clouds.yaml make test-conformance` +# The -stream flag will make Ginkgo print results to the screen in real-time. + +managementClusterName: capo-e2e + +images: +- name: gcr.io/k8s-staging-cluster-api/cluster-api-controller:nightly_master_20210310 + loadBehavior: tryLoad +- name: gcr.io/k8s-staging-cluster-api/kubeadm-bootstrap-controller:nightly_master_20210310 + loadBehavior: tryLoad +- name: gcr.io/k8s-staging-cluster-api/kubeadm-control-plane-controller:nightly_master_20210310 + loadBehavior: tryLoad +# Use local dev images built source tree; +- name: gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:e2e + loadBehavior: mustLoad +- name: quay.io/jetstack/cert-manager-cainjector:v1.1.0 + loadBehavior: tryLoad +- name: quay.io/jetstack/cert-manager-webhook:v1.1.0 + loadBehavior: tryLoad +- name: quay.io/jetstack/cert-manager-controller:v1.1.0 + loadBehavior: tryLoad + +providers: +- name: cluster-api + type: CoreProvider + versions: + - name: v0.4.0 + value: https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/nightly_master_20210310/core-components.yaml + type: url + files: + - sourcePath: "../data/shared/v1alpha4/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" + - old: "--leader-elect" + new: "--leader-elect=false" +- name: kubeadm + type: BootstrapProvider + versions: + - name: v0.4.0 + value: https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/nightly_master_20210310/bootstrap-components.yaml + type: url + files: + - sourcePath: "../data/shared/v1alpha4/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" + - old: "--leader-elect" + new: "--leader-elect=false" +- name: kubeadm + type: ControlPlaneProvider + versions: + - name: v0.4.0 + value: https://storage.googleapis.com/artifacts.k8s-staging-cluster-api.appspot.com/components/nightly_master_20210310/control-plane-components.yaml + type: url + files: + - sourcePath: "../data/shared/v1alpha4/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" + - old: "--leader-elect" + new: "--leader-elect=false" +- name: openstack + type: InfrastructureProvider + versions: + - name: v0.4.0 + value: ../../../config/default + files: + - sourcePath: "../data/shared/v1alpha4_provider/metadata.yaml" + - sourcePath: "./infrastructure-openstack/cluster-template.yaml" + - sourcePath: "./infrastructure-openstack/cluster-template-external-cloud-provider.yaml" + - sourcePath: "./infrastructure-openstack/cluster-template-without-lb.yaml" + replacements: + - old: gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:dev + new: gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:e2e + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" + - old: "--v=2" + new: "--v=4" + +# default variables for the e2e test; those values could be overridden via env variables, thus +# allowing the same e2e config file to be re-used in different prow jobs e.g. each one with a K8s version permutation +variables: + # used to ensure we deploy to the correct management cluster + KUBE_CONTEXT: "kind-capo-e2e" + KUBERNETES_VERSION: "v1.20.4" + CNI: "../../data/cni/calico.yaml" + EXP_CLUSTER_RESOURCE_SET: "true" + OPENSTACK_BASTION_IMAGE_NAME: "cirros-0.5.1-x86_64-disk" + OPENSTACK_BASTION_MACHINE_FLAVOR: "m1.tiny" + OPENSTACK_CLOUD: "capo-e2e" + OPENSTACK_CLOUD_CACERT_B64: "Cg==" + OPENSTACK_CLOUD_YAML_FILE: '../../../../clouds.yaml' + OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR: "m1.medium" + OPENSTACK_DNS_NAMESERVERS: "8.8.8.8" + OPENSTACK_FAILURE_DOMAIN: "nova" + OPENSTACK_IMAGE_NAME: "ubuntu-2004-kube-v1.18.15" + OPENSTACK_NODE_MACHINE_FLAVOR: "m1.small" + OPENSTACK_SSH_KEY_NAME: "cluster-api-provider-openstack-sigs-k8s-io" + CONFORMANCE_WORKER_MACHINE_COUNT: "5" + CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT: "1" + +intervals: + conformance/wait-control-plane: ["30m", "10s"] + conformance/wait-worker-nodes: ["30m", "10s"] + default/wait-controllers: ["3m", "10s"] + default/wait-cluster: ["20m", "10s"] + default/wait-control-plane: ["20m", "10s"] + default/wait-worker-nodes: ["20m", "10s"] + default/wait-delete-cluster: ["30m", "10s"] + default/wait-machine-status: ["20m", "10s"] diff --git a/test/e2e/data/infrastructure-openstack/cluster-template-external-cloud-provider.yaml b/test/e2e/data/infrastructure-openstack/cluster-template-external-cloud-provider.yaml new file mode 100644 index 0000000000..3ed184ff4d --- /dev/null +++ b/test/e2e/data/infrastructure-openstack/cluster-template-external-cloud-provider.yaml @@ -0,0 +1,166 @@ +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: Cluster +metadata: + name: ${CLUSTER_NAME} + labels: + cni: "${CLUSTER_NAME}-crs-0" +spec: + clusterNetwork: + pods: + cidrBlocks: ["192.168.0.0/16"] # CIDR block used by Calico. + serviceDomain: "cluster.local" + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackCluster + name: ${CLUSTER_NAME} + controlPlaneRef: + kind: KubeadmControlPlane + apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 + name: ${CLUSTER_NAME}-control-plane +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackCluster +metadata: + name: ${CLUSTER_NAME} +spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + managedAPIServerLoadBalancer: true + managedSecurityGroups: true + nodeCidr: 10.6.0.0/24 + dnsNameservers: + - ${OPENSTACK_DNS_NAMESERVERS} + useOctavia: true + bastion: + enabled: true + instance: + flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR} + image: ${OPENSTACK_BASTION_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +kind: KubeadmControlPlane +apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 +metadata: + name: "${CLUSTER_NAME}-control-plane" +spec: + replicas: ${CONTROL_PLANE_MACHINE_COUNT} + infrastructureTemplate: + kind: OpenStackMachineTemplate + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + name: "${CLUSTER_NAME}-control-plane" + kubeadmConfigSpec: + initConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-provider: external + clusterConfiguration: + imageRepository: k8s.gcr.io + apiServer: + extraArgs: + cloud-provider: external + controllerManager: + extraArgs: + cloud-provider: external + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-provider: external + version: "${KUBERNETES_VERSION}" +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane +spec: + template: + spec: + flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: MachineDeployment +metadata: + name: "${CLUSTER_NAME}-md-0" +spec: + clusterName: "${CLUSTER_NAME}" + replicas: ${WORKER_MACHINE_COUNT} + selector: + matchLabels: + template: + spec: + clusterName: "${CLUSTER_NAME}" + version: "${KUBERNETES_VERSION}" + failureDomain: ${OPENSTACK_FAILURE_DOMAIN} + bootstrap: + configRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 + kind: KubeadmConfigTemplate + infrastructureRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackMachineTemplate +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 +kind: KubeadmConfigTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-provider: external +--- +apiVersion: v1 +kind: Secret +metadata: + name: ${CLUSTER_NAME}-cloud-config + labels: + clusterctl.cluster.x-k8s.io/move: "true" +data: + clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} + cacert: ${OPENSTACK_CLOUD_CACERT_B64} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: "cni-${CLUSTER_NAME}-crs-0" +data: ${CNI_RESOURCES} +--- +apiVersion: addons.cluster.x-k8s.io/v1alpha4 +kind: ClusterResourceSet +metadata: + name: "${CLUSTER_NAME}-crs-0" +spec: + strategy: ApplyOnce + clusterSelector: + matchLabels: + cni: "${CLUSTER_NAME}-crs-0" + resources: + - name: "cni-${CLUSTER_NAME}-crs-0" + kind: ConfigMap diff --git a/test/e2e/data/infrastructure-openstack/cluster-template-without-lb.yaml b/test/e2e/data/infrastructure-openstack/cluster-template-without-lb.yaml new file mode 100644 index 0000000000..e34fa76171 --- /dev/null +++ b/test/e2e/data/infrastructure-openstack/cluster-template-without-lb.yaml @@ -0,0 +1,205 @@ +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: Cluster +metadata: + name: ${CLUSTER_NAME} + labels: + cni: "${CLUSTER_NAME}-crs-0" +spec: + clusterNetwork: + pods: + cidrBlocks: ["192.168.0.0/16"] # CIDR block used by Calico. + serviceDomain: "cluster.local" + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackCluster + name: ${CLUSTER_NAME} + controlPlaneRef: + kind: KubeadmControlPlane + apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 + name: ${CLUSTER_NAME}-control-plane +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackCluster +metadata: + name: ${CLUSTER_NAME} +spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + managedSecurityGroups: true + nodeCidr: 10.6.0.0/24 + dnsNameservers: + - ${OPENSTACK_DNS_NAMESERVERS} + bastion: + enabled: true + instance: + flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR} + image: ${OPENSTACK_BASTION_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +kind: KubeadmControlPlane +apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 +metadata: + name: "${CLUSTER_NAME}-control-plane" +spec: + replicas: 1 + infrastructureTemplate: + kind: OpenStackMachineTemplate + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + name: "${CLUSTER_NAME}-control-plane" + kubeadmConfigSpec: + initConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + clusterConfiguration: + imageRepository: k8s.gcr.io + apiServer: + extraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + extraVolumes: + - name: cloud + hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + readOnly: true + controllerManager: + extraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + extraVolumes: + - name: cloud + hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + readOnly: true + - name: cacerts + hostPath: /etc/certs/cacert + mountPath: /etc/certs/cacert + readOnly: true + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + files: + - path: /etc/kubernetes/cloud.conf + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + - path: /etc/certs/cacert + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + version: "${KUBERNETES_VERSION}" +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane +spec: + template: + spec: + flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: MachineDeployment +metadata: + name: "${CLUSTER_NAME}-md-0" +spec: + clusterName: "${CLUSTER_NAME}" + replicas: ${WORKER_MACHINE_COUNT} + selector: + matchLabels: + template: + spec: + clusterName: "${CLUSTER_NAME}" + version: "${KUBERNETES_VERSION}" + failureDomain: ${OPENSTACK_FAILURE_DOMAIN} + bootstrap: + configRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 + kind: KubeadmConfigTemplate + infrastructureRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackMachineTemplate +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 +kind: KubeadmConfigTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + files: + - content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack +--- +apiVersion: v1 +kind: Secret +metadata: + name: ${CLUSTER_NAME}-cloud-config + labels: + clusterctl.cluster.x-k8s.io/move: "true" +data: + clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} + cacert: ${OPENSTACK_CLOUD_CACERT_B64} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: "cni-${CLUSTER_NAME}-crs-0" +data: ${CNI_RESOURCES} +--- +apiVersion: addons.cluster.x-k8s.io/v1alpha4 +kind: ClusterResourceSet +metadata: + name: "${CLUSTER_NAME}-crs-0" +spec: + strategy: ApplyOnce + clusterSelector: + matchLabels: + cni: "${CLUSTER_NAME}-crs-0" + resources: + - name: "cni-${CLUSTER_NAME}-crs-0" + kind: ConfigMap diff --git a/test/e2e/data/infrastructure-openstack/cluster-template.yaml b/test/e2e/data/infrastructure-openstack/cluster-template.yaml new file mode 100644 index 0000000000..cf5d795457 --- /dev/null +++ b/test/e2e/data/infrastructure-openstack/cluster-template.yaml @@ -0,0 +1,219 @@ +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: Cluster +metadata: + name: ${CLUSTER_NAME} + labels: + cni: "${CLUSTER_NAME}-crs-0" +spec: + clusterNetwork: + pods: + cidrBlocks: ["192.168.0.0/16"] # CIDR block used by Calico. + serviceDomain: "cluster.local" + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackCluster + name: ${CLUSTER_NAME} + controlPlaneRef: + kind: KubeadmControlPlane + apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 + name: ${CLUSTER_NAME}-control-plane +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackCluster +metadata: + name: ${CLUSTER_NAME} +spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + managedAPIServerLoadBalancer: true + managedSecurityGroups: true + nodeCidr: 10.6.0.0/24 + dnsNameservers: + - ${OPENSTACK_DNS_NAMESERVERS} + useOctavia: true + bastion: + enabled: true + instance: + flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR} + image: ${OPENSTACK_BASTION_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +kind: KubeadmControlPlane +apiVersion: controlplane.cluster.x-k8s.io/v1alpha4 +metadata: + name: "${CLUSTER_NAME}-control-plane" +spec: + replicas: ${CONTROL_PLANE_MACHINE_COUNT} + infrastructureTemplate: + kind: OpenStackMachineTemplate + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + name: "${CLUSTER_NAME}-control-plane" + kubeadmConfigSpec: + initConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + clusterConfiguration: + imageRepository: k8s.gcr.io + apiServer: + extraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + extraVolumes: + - name: cloud + hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + readOnly: true + controllerManager: + extraArgs: + cloud-provider: openstack + cloud-config: /etc/kubernetes/cloud.conf + extraVolumes: + - name: cloud + hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + readOnly: true + - name: cacerts + hostPath: /etc/certs/cacert + mountPath: /etc/certs/cacert + readOnly: true + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + files: + - path: /etc/kubernetes/cloud.conf + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + - path: /etc/certs/cacert + owner: root + permissions: "0600" + content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + users: + - name: "capi" + sudo: "ALL=(ALL) NOPASSWD:ALL" + # user: capi, passwd: capi + passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" + lockPassword: false + version: "${KUBERNETES_VERSION}" +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane +spec: + template: + spec: + flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config +--- +apiVersion: cluster.x-k8s.io/v1alpha4 +kind: MachineDeployment +metadata: + name: "${CLUSTER_NAME}-md-0" +spec: + clusterName: "${CLUSTER_NAME}" + replicas: ${WORKER_MACHINE_COUNT} + selector: + matchLabels: + template: + spec: + clusterName: "${CLUSTER_NAME}" + version: "${KUBERNETES_VERSION}" + failureDomain: ${OPENSTACK_FAILURE_DOMAIN} + bootstrap: + configRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 + kind: KubeadmConfigTemplate + infrastructureRef: + name: "${CLUSTER_NAME}-md-0" + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 + kind: OpenStackMachineTemplate +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + cloudName: ${OPENSTACK_CLOUD} + cloudsSecret: + name: ${CLUSTER_NAME}-cloud-config + flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} + image: ${OPENSTACK_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 +kind: KubeadmConfigTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 +spec: + template: + spec: + files: + - content: ${OPENSTACK_CLOUD_PROVIDER_CONF_B64} + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: ${OPENSTACK_CLOUD_CACERT_B64} + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" + joinConfiguration: + nodeRegistration: + name: '{{ local_hostname }}' + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + users: + - name: "capi" + sudo: "ALL=(ALL) NOPASSWD:ALL" + # user: capi, passwd: capi + passwd: "$6$rounds=4096$yKTFKL6RmN128$a7cGMiNjeTSd091s6QzZcUNrMTgm3HhML5rVmpDFlCfgD7scTW7ZHr0OChcXCaeiO/kbhdn0XzIzWk63nSqRH1" + lockPassword: false +--- +apiVersion: v1 +kind: Secret +metadata: + name: ${CLUSTER_NAME}-cloud-config + labels: + clusterctl.cluster.x-k8s.io/move: "true" +data: + clouds.yaml: ${OPENSTACK_CLOUD_YAML_B64} + cacert: ${OPENSTACK_CLOUD_CACERT_B64} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: "cni-${CLUSTER_NAME}-crs-0" +data: ${CNI_RESOURCES} +--- +apiVersion: addons.cluster.x-k8s.io/v1alpha4 +kind: ClusterResourceSet +metadata: + name: "${CLUSTER_NAME}-crs-0" +spec: + strategy: ApplyOnce + clusterSelector: + matchLabels: + cni: "${CLUSTER_NAME}-crs-0" + resources: + - name: "cni-${CLUSTER_NAME}-crs-0" + kind: ConfigMap diff --git a/test/e2e/data/kubetest/conformance-fast.yaml b/test/e2e/data/kubetest/conformance-fast.yaml new file mode 100644 index 0000000000..b02c7ae14e --- /dev/null +++ b/test/e2e/data/kubetest/conformance-fast.yaml @@ -0,0 +1,8 @@ +ginkgo.focus: \[Conformance\] +ginkgo.skip: .*\[Serial\].* +disable-log-dump: true +ginkgo.progress: true +ginkgo.slowSpecThreshold: 120.0 +ginkgo.flakeAttempts: 3 +ginkgo.trace: true +ginkgo.v: true diff --git a/test/e2e/data/kubetest/conformance.yaml b/test/e2e/data/kubetest/conformance.yaml new file mode 100644 index 0000000000..d748f43288 --- /dev/null +++ b/test/e2e/data/kubetest/conformance.yaml @@ -0,0 +1,7 @@ +ginkgo.focus: \[Conformance\] +disable-log-dump: true +ginkgo.progress: true +ginkgo.slowSpecThreshold: 120.0 +ginkgo.flakeAttempts: 3 +ginkgo.trace: true +ginkgo.v: true diff --git a/test/e2e/data/shared/v1alpha4/metadata.yaml b/test/e2e/data/shared/v1alpha4/metadata.yaml new file mode 100644 index 0000000000..0f32871ff4 --- /dev/null +++ b/test/e2e/data/shared/v1alpha4/metadata.yaml @@ -0,0 +1,6 @@ +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +releaseSeries: + - major: 0 + minor: 4 + contract: v1alpha4 diff --git a/test/e2e/data/shared/v1alpha4_provider/metadata.yaml b/test/e2e/data/shared/v1alpha4_provider/metadata.yaml new file mode 100644 index 0000000000..b61e48c523 --- /dev/null +++ b/test/e2e/data/shared/v1alpha4_provider/metadata.yaml @@ -0,0 +1,9 @@ +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +releaseSeries: +- major: 0 + minor: 3 + contract: v1alpha3 +- major: 0 + minor: 4 + contract: v1alpha4 diff --git a/test/e2e/shared/cluster.go b/test/e2e/shared/cluster.go new file mode 100644 index 0000000000..6879f63833 --- /dev/null +++ b/test/e2e/shared/cluster.go @@ -0,0 +1,107 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "context" + "path/filepath" + + . "github.com/onsi/gomega" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/clientcmd" + capie2e "sigs.k8s.io/cluster-api/test/e2e" + "sigs.k8s.io/cluster-api/test/framework" + "sigs.k8s.io/cluster-api/test/framework/bootstrap" + "sigs.k8s.io/cluster-api/test/framework/clusterctl" +) + +// createClusterctlLocalRepository generates a clusterctl repository. +// Must always be run after kubetest.NewConfiguration +func createClusterctlLocalRepository(config *clusterctl.E2EConfig, repositoryFolder string) string { + createRepositoryInput := clusterctl.CreateRepositoryInput{ + E2EConfig: config, + RepositoryFolder: repositoryFolder, + } + + // Ensuring a CNI file is defined in the config and register a FileTransformation to inject the referenced file as in place of the CNI_RESOURCES envSubst variable. + Expect(config.Variables).To(HaveKey(capie2e.CNIPath), "Missing %s variable in the config", capie2e.CNIPath) + cniPath := config.GetVariable(capie2e.CNIPath) + Expect(cniPath).To(BeAnExistingFile(), "The %s variable should resolve to an existing file", capie2e.CNIPath) + createRepositoryInput.RegisterClusterResourceSetConfigMapTransformation(cniPath, capie2e.CNIResources) + + clusterctlConfig := clusterctl.CreateRepository(context.TODO(), createRepositoryInput) + Expect(clusterctlConfig).To(BeAnExistingFile(), "The clusterctl config file does not exists in the local repository %s", repositoryFolder) + return clusterctlConfig +} + +// setupBootstrapCluster installs Cluster API components via clusterctl +func setupBootstrapCluster(config *clusterctl.E2EConfig, scheme *runtime.Scheme, useExistingCluster bool) (bootstrap.ClusterProvider, framework.ClusterProxy) { + var clusterProvider bootstrap.ClusterProvider + kubeconfigPath := "" + if !useExistingCluster { + clusterProvider = bootstrap.CreateKindBootstrapClusterAndLoadImages(context.TODO(), bootstrap.CreateKindBootstrapClusterAndLoadImagesInput{ + Name: config.ManagementClusterName, + RequiresDockerSock: config.HasDockerProvider(), + Images: config.Images, + }) + Expect(clusterProvider).ToNot(BeNil(), "Failed to create a bootstrap cluster") + + kubeconfigPath = clusterProvider.GetKubeconfigPath() + Expect(kubeconfigPath).To(BeAnExistingFile(), "Failed to get the kubeconfig file for the bootstrap cluster") + } + + // Ensure kubeconfigPath already has been defaulted for the verification below + // If we're not doing it here, it's done inside of framework.NewClusterProxy() + if kubeconfigPath == "" { + kubeconfigPath = clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename() + } + + kubeContext := config.GetVariable(KubeContext) + if kubeContext != "" { + kubecfg, err := clientcmd.LoadFromFile(kubeconfigPath) + Expect(err).NotTo(HaveOccurred()) + Expect(kubecfg.CurrentContext).Should(Equal(kubeContext), "current-context of the kubeconfig should be the same as %s (%s)", KubeContext, kubeContext) + } + + clusterProxy := framework.NewClusterProxy("bootstrap", kubeconfigPath, scheme) + Expect(clusterProxy).ToNot(BeNil(), "Failed to get a bootstrap cluster proxy") + + return clusterProvider, clusterProxy +} + +// initBootstrapCluster uses kind to create a cluster +func initBootstrapCluster(e2eCtx *E2EContext) { + clusterctl.InitManagementClusterAndWatchControllerLogs(context.TODO(), clusterctl.InitManagementClusterAndWatchControllerLogsInput{ + ClusterProxy: e2eCtx.Environment.BootstrapClusterProxy, + ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, + InfrastructureProviders: e2eCtx.E2EConfig.InfrastructureProviders(), + LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName()), + }, e2eCtx.E2EConfig.GetIntervals(e2eCtx.Environment.BootstrapClusterProxy.GetName(), "wait-controllers")...) +} + +// tearDown the bootstrap kind cluster +func tearDown(bootstrapClusterProvider bootstrap.ClusterProvider, bootstrapClusterProxy framework.ClusterProxy) { + if bootstrapClusterProxy != nil { + bootstrapClusterProxy.Dispose(context.TODO()) + } + if bootstrapClusterProvider != nil { + bootstrapClusterProvider.Dispose(context.TODO()) + } +} diff --git a/test/e2e/shared/common.go b/test/e2e/shared/common.go new file mode 100644 index 0000000000..eec5926557 --- /dev/null +++ b/test/e2e/shared/common.go @@ -0,0 +1,212 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "context" + "fmt" + "os" + "path" + "path/filepath" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/cluster-api/test/framework" + "sigs.k8s.io/cluster-api/test/framework/clusterctl" + "sigs.k8s.io/cluster-api/util" + "sigs.k8s.io/controller-runtime/pkg/client" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha4" +) + +func SetupSpecNamespace(ctx context.Context, specName string, e2eCtx *E2EContext) *corev1.Namespace { + Byf("Creating a namespace for hosting the %q test spec", specName) + namespace, cancelWatches := framework.CreateNamespaceAndWatchEvents(ctx, framework.CreateNamespaceAndWatchEventsInput{ + Creator: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), + ClientSet: e2eCtx.Environment.BootstrapClusterProxy.GetClientSet(), + Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6)), + LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName()), + }) + + e2eCtx.Environment.Namespaces[namespace] = cancelWatches + + return namespace +} + +func DumpSpecResourcesAndCleanup(ctx context.Context, specName string, namespace *corev1.Namespace, e2eCtx *E2EContext) { + Byf("Dumping all the Cluster API resources in the %q namespace", namespace.Name) + // Dump all Cluster API related resources to artifacts before deleting them. + cancelWatches := e2eCtx.Environment.Namespaces[namespace] + DumpSpecResources(ctx, e2eCtx, namespace) + Byf("Dumping all OpenStack server instances in the %q namespace", namespace.Name) + DumpMachines(ctx, e2eCtx, namespace) + if !e2eCtx.Settings.SkipCleanup { + framework.DeleteAllClustersAndWait(ctx, framework.DeleteAllClustersAndWaitInput{ + Client: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), + Namespace: namespace.Name, + }, e2eCtx.E2EConfig.GetIntervals(specName, "wait-delete-cluster")...) + + Byf("Deleting namespace used for hosting the %q test spec", specName) + framework.DeleteNamespace(ctx, framework.DeleteNamespaceInput{ + Deleter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), + Name: namespace.Name, + }) + } + cancelWatches() + delete(e2eCtx.Environment.Namespaces, namespace) +} + +func DumpMachines(ctx context.Context, e2eCtx *E2EContext, namespace *corev1.Namespace) { + By("Running DumpMachines") + cluster := ClusterForSpec(ctx, e2eCtx.Environment.BootstrapClusterProxy, namespace) + if cluster.Status.Bastion == nil || cluster.Status.Bastion.FloatingIP == "" { + _, _ = fmt.Fprintln(GinkgoWriter, "cannot dump machines, cluster doesn't have a bastion host with a floating ip") + return + } + machines := MachinesForSpec(ctx, e2eCtx.Environment.BootstrapClusterProxy, namespace) + instances, err := allMachines(ctx, e2eCtx) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "cannot dump machines, could not get instances from OpenStack: %v\n", err) + return + } + var machineInstance instance + for _, m := range machines.Items { + for _, i := range instances { + if i.name == m.Name { + machineInstance = i + break + } + } + if machineInstance.id == "" { + return + } + DumpMachine(ctx, e2eCtx, m, machineInstance, cluster.Status.Bastion.FloatingIP) + } +} + +func ClusterForSpec(ctx context.Context, clusterProxy framework.ClusterProxy, namespace *corev1.Namespace) *infrav1.OpenStackCluster { + lister := clusterProxy.GetClient() + list := new(infrav1.OpenStackClusterList) + if err := lister.List(ctx, list, client.InNamespace(namespace.GetName())); err != nil { + _, _ = fmt.Fprintln(GinkgoWriter, "couldn't find cluster") + return nil + } + Expect(list.Items).To(HaveLen(1), "Expected to find one cluster, found %d", len(list.Items)) + return &list.Items[0] +} + +func MachinesForSpec(ctx context.Context, clusterProxy framework.ClusterProxy, namespace *corev1.Namespace) *infrav1.OpenStackMachineList { + lister := clusterProxy.GetClient() + list := new(infrav1.OpenStackMachineList) + if err := lister.List(ctx, list, client.InNamespace(namespace.GetName())); err != nil { + _, _ = fmt.Fprintln(GinkgoWriter, "couldn't find machines") + return nil + } + return list +} + +func DumpMachine(_ context.Context, e2eCtx *E2EContext, machine infrav1.OpenStackMachine, machineInstance instance, bastionIP string) { + logPath := filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName()) + machineLogBase := path.Join(logPath, "instances", machine.Namespace, machine.Name) + metaLog := path.Join(machineLogBase, "instance.log") + if err := os.MkdirAll(filepath.Dir(metaLog), 0750); err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't create directory %q for file: %s", metaLog, err) + } + f, err := os.OpenFile(metaLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't open file %q: %s", metaLog, err) + return + } + defer f.Close() + + _, _ = fmt.Fprintf(f, "instance found: %q\n", machineInstance.id) + commandsForMachine( + f, + machineInstance.ip, + bastionIP, + []command{ + // don't do this for now, it just takes to long + //{ + // title: "systemd", + // cmd: "journalctl --no-pager --output=short-precise | grep -v 'audit:\\|audit\\['", + //}, + { + title: "kern", + cmd: "journalctl --no-pager --output=short-precise -k", + }, + { + title: "containerd-info", + cmd: "crictl info", + }, + { + title: "containerd-containers", + cmd: "crictl ps", + }, + { + title: "containerd-pods", + cmd: "crictl pods", + }, + { + title: "cloud-final", + cmd: "journalctl --no-pager -u cloud-final", + }, + { + title: "kubelet", + cmd: "journalctl --no-pager -u kubelet.service", + }, + { + title: "containerd", + cmd: "journalctl --no-pager -u containerd.service", + }, + }, + ) +} + +func DumpSpecResources(ctx context.Context, e2eCtx *E2EContext, namespace *corev1.Namespace) { + framework.DumpAllResources(ctx, framework.DumpAllResourcesInput{ + Lister: e2eCtx.Environment.BootstrapClusterProxy.GetClient(), + Namespace: namespace.Name, + LogPath: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName(), "resources"), + }) +} + +func Byf(format string, a ...interface{}) { + By(fmt.Sprintf(format, a...)) +} + +// LoadE2EConfig loads the e2econfig from the specified path +func LoadE2EConfig(configPath string) *clusterctl.E2EConfig { + config := clusterctl.LoadE2EConfig(context.TODO(), clusterctl.LoadE2EConfigInput{ConfigPath: configPath}) + Expect(config).ToNot(BeNil(), "Failed to load E2E config from %s", configPath) + return config +} + +// SetEnvVar sets an environment variable in the process. If marked private, +// the value is not printed. +func SetEnvVar(key, value string, private bool) { + printableValue := "*******" + if !private { + printableValue = value + } + + Byf("Setting environment variable: key=%s, value=%s", key, printableValue) + _ = os.Setenv(key, value) +} diff --git a/test/e2e/shared/context.go b/test/e2e/shared/context.go new file mode 100644 index 0000000000..e0fdc7cc03 --- /dev/null +++ b/test/e2e/shared/context.go @@ -0,0 +1,104 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "context" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api/test/framework" + "sigs.k8s.io/cluster-api/test/framework/bootstrap" + "sigs.k8s.io/cluster-api/test/framework/clusterctl" +) + +// Option represents an option to use when creating a e2e context +type Option func(*E2EContext) + +func NewE2EContext(options ...Option) *E2EContext { + ctx := &E2EContext{} + ctx.Environment.Scheme = DefaultScheme() + ctx.Environment.Namespaces = map[*corev1.Namespace]context.CancelFunc{} + //ctx.Lifecycle = DefaultGinkgoLifecycle() + + for _, opt := range options { + opt(ctx) + } + + return ctx +} + +// E2EContext represents the context of the e2e test +type E2EContext struct { + // Settings is the settings used for the test + Settings Settings + // E2EConfig to be used for this test, read from configPath. + E2EConfig *clusterctl.E2EConfig + // Environment represents the runtime environment + Environment RuntimeEnvironment +} + +// Settings represents the test settings +type Settings struct { + // ConfigPath is the path to the e2e config file. + ConfigPath string + // useExistingCluster instructs the test to use the current cluster instead of creating a new one (default discovery rules apply). + UseExistingCluster bool + // ArtifactFolder is the folder to store e2e test artifacts. + ArtifactFolder string + // DataFolder is the root folder for the data required by the tests + DataFolder string + // SkipCleanup prevents cleanup of test resources e.g. for debug purposes. + SkipCleanup bool + // number of ginkgo nodes to use for kubetest + GinkgoNodes int + // time in s before kubetest spec is marked as slow + GinkgoSlowSpecThreshold int + // kubetestConfigFilePath is the path to the kubetest configuration file + KubetestConfigFilePath string + // useCIArtifacts specifies whether or not to use the latest build from the main branch of the Kubernetes repository + UseCIArtifacts bool + // SourceTemplate specifies which source template to use + SourceTemplate string +} + +// RuntimeEnvironment represents the runtime environment of the test +type RuntimeEnvironment struct { + // BootstrapClusterProvider manages provisioning of the the bootstrap cluster to be used for the e2e tests. + // Please note that provisioning will be skipped if use-existing-cluster is provided. + BootstrapClusterProvider bootstrap.ClusterProvider + // BootstrapClusterProxy allows to interact with the bootstrap cluster to be used for the e2e tests. + BootstrapClusterProxy framework.ClusterProxy + // ResourceTicker for dumping resources + ResourceTicker *time.Ticker + // ResourceTickerDone to stop ticking + ResourceTickerDone chan bool + // MachineTicker for dumping resources + MachineTicker *time.Ticker + // MachineTickerDone to stop ticking + MachineTickerDone chan bool + // Namespaces holds the namespaces used in the tests + Namespaces map[*corev1.Namespace]context.CancelFunc + // ClusterctlConfigPath to be used for this test, created by generating a clusterctl local repository + // with the providers specified in the configPath. + ClusterctlConfigPath string + // Scheme is the GVK scheme to use for the tests + Scheme *runtime.Scheme +} diff --git a/test/e2e/shared/defaults.go b/test/e2e/shared/defaults.go new file mode 100644 index 0000000000..f803d7f376 --- /dev/null +++ b/test/e2e/shared/defaults.go @@ -0,0 +1,59 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "flag" + + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha4" + "sigs.k8s.io/cluster-api/test/framework" +) + +const ( + DefaultSSHKeyPairName = "cluster-api-provider-openstack-sigs-k8s-io" + KubeContext = "KUBE_CONTEXT" + KubernetesVersion = "KUBERNETES_VERSION" + OpenStackCloudYAMLFile = "OPENSTACK_CLOUD_YAML_FILE" + OpenStackCloud = "OPENSTACK_CLOUD" +) + +// DefaultScheme returns the default scheme to use for testing +func DefaultScheme() *runtime.Scheme { + sc := runtime.NewScheme() + framework.TryAddDefaultSchemes(sc) + _ = v1alpha4.AddToScheme(sc) + _ = clientgoscheme.AddToScheme(sc) + return sc +} + +// CreateDefaultFlags will create the default flags used for the tests and binds them to the e2e context +func CreateDefaultFlags(ctx *E2EContext) { + flag.StringVar(&ctx.Settings.ConfigPath, "config-path", "", "path to the e2e config file") + flag.StringVar(&ctx.Settings.ArtifactFolder, "artifacts-folder", "", "folder where e2e test artifact should be stored") + flag.BoolVar(&ctx.Settings.UseCIArtifacts, "kubetest.use-ci-artifacts", false, "use the latest build from the main branch of the Kubernetes repository") + flag.StringVar(&ctx.Settings.KubetestConfigFilePath, "kubetest.config-file", "", "path to the kubetest configuration file") + flag.IntVar(&ctx.Settings.GinkgoNodes, "kubetest.ginkgo-nodes", 1, "number of ginkgo nodes to use") + flag.IntVar(&ctx.Settings.GinkgoSlowSpecThreshold, "kubetest.ginkgo-slowSpecThreshold", 120, "time in s before spec is marked as slow") + flag.BoolVar(&ctx.Settings.UseExistingCluster, "use-existing-cluster", false, "if true, the test uses the current cluster instead of creating a new one (default discovery rules apply)") + flag.BoolVar(&ctx.Settings.SkipCleanup, "skip-cleanup", false, "if true, the resource cleanup after tests will be skipped") + flag.StringVar(&ctx.Settings.DataFolder, "data-folder", "", "path to the data folder") + flag.StringVar(&ctx.Settings.SourceTemplate, "source-template", "./infrastructure-openstack/cluster-template.yaml", "path to the data folder") +} diff --git a/test/e2e/shared/exec.go b/test/e2e/shared/exec.go new file mode 100644 index 0000000000..75b312ebc2 --- /dev/null +++ b/test/e2e/shared/exec.go @@ -0,0 +1,177 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "bytes" + "context" + "fmt" + "net" + "os" + "path" + "path/filepath" + "strings" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" + . "github.com/onsi/ginkgo" + "golang.org/x/crypto/ssh" + + "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/compute" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/provider" +) + +type instance struct { + name string + id string + ip string +} + +// allMachines gets all OpenStack servers at once, to save on DescribeInstances +// calls +func allMachines(_ context.Context, e2eCtx *E2EContext) ([]instance, error) { + openStackCloudYAMLFile := e2eCtx.E2EConfig.GetVariable(OpenStackCloudYAMLFile) + openstackCloud := e2eCtx.E2EConfig.GetVariable(OpenStackCloud) + + clouds := getParsedOpenStackCloudYAML(openStackCloudYAMLFile) + cloud := clouds.Clouds[openstackCloud] + + providerClient, clientOpts, err := provider.NewClient(cloud, nil) + if err != nil { + return nil, fmt.Errorf("error creating provider client: %v", err) + } + + computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{Region: clientOpts.RegionName}) + if err != nil { + return nil, fmt.Errorf("error creating compute client: %v", err) + } + + serverListOpts := &servers.ListOpts{} + allPages, err := servers.List(computeClient, serverListOpts).AllPages() + if err != nil { + return nil, fmt.Errorf("error listing server: %v", err) + } + + serverList, err := servers.ExtractServers(allPages) + if err != nil { + return nil, fmt.Errorf("error extracting server: %v", err) + } + + instances := make([]instance, len(serverList)) + for _, server := range serverList { + addrMap, err := compute.GetIPFromInstance(server) + if err != nil { + return nil, fmt.Errorf("error getting ip for server %s: %v", server.Name, err) + } + ip, ok := addrMap["internal"] + if !ok { + return nil, fmt.Errorf("error geting internal ip for server %s: %v", server.Name, err) + } + + instances = append(instances, instance{ + name: server.Name, + id: server.ID, + ip: ip, + }) + } + return instances, nil +} + +type command struct { + title string + cmd string +} + +// commandsForMachine opens a terminal connection +// and executes the given commands, outputting the results to a file for each. +func commandsForMachine(f *os.File, machineIP, bastionIP string, commands []command) { + // TODO(sbuerin) try to access via ssh key pair as soon as it's clear how to do that + // Issue: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/issues/784 + //providerClient, clientOpts, err := getProviderClient(e2eCtx) + //computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{ + // Region: clientOpts.RegionName, + //}) + //keyPair, err := keypairs.Get(computeClient, DefaultSSHKeyPairName).Extract() + // Get a signer from the private key file + //signer, err := ssh.ParsePrivateKey([]byte(keyPair.PrivateKey)) + + cfg := &ssh.ClientConfig{ + User: "cirros", + Auth: []ssh.AuthMethod{ssh.Password("gocubsgo")}, + HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, + } + cfg.SetDefaults() + + // connect to the bastion host + bastionConn, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", bastionIP), cfg) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't connect to bastion host %s: %s", bastionIP, err) + return + } + defer bastionConn.Close() + + // Dial a connection to the service host, from the bastion host + conn, err := bastionConn.Dial("tcp", fmt.Sprintf("%s:22", machineIP)) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't connect from the bastion host %s to the target instance %s: %s", bastionIP, machineIP, err) + return + } + defer conn.Close() + + // connect to the machineInstance via hte bastion host + cfg = &ssh.ClientConfig{ + User: "capi", + Auth: []ssh.AuthMethod{ssh.Password("capi")}, + HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, + } + cfg.SetDefaults() + clientConn, channels, reqs, err := ssh.NewClientConn(conn, machineIP, cfg) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't connect from local to the target instance %s: %s", machineIP, err) + return + } + defer clientConn.Close() + + sshClient := ssh.NewClient(clientConn, channels, reqs) + + for _, c := range commands { + session, err := sshClient.NewSession() + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "couldn't open session from local to the target instance %s: %s", machineIP, err) + continue + } + defer session.Close() + + logFile := path.Join(filepath.Dir(f.Name()), c.title+".log") + var stdoutBuf bytes.Buffer + var stderrBuf bytes.Buffer + session.Stdout = &stdoutBuf + session.Stderr = &stderrBuf + if err := session.Run("sudo " + c.cmd + "\n"); err != nil { + _, _ = fmt.Fprintf(f, "unable to send command %q: %s\n", c.cmd, err) + continue + } + result := strings.TrimSuffix(stdoutBuf.String(), "\n") + "\n" + strings.TrimSuffix(stderrBuf.String(), "\n") + if err := os.WriteFile(logFile, []byte(result), os.ModePerm); err != nil { + _, _ = fmt.Fprintf(f, "error writing log file: %s", err) + continue + } + } +} diff --git a/test/e2e/shared/exec_test.go b/test/e2e/shared/exec_test.go new file mode 100644 index 0000000000..793260e6c7 --- /dev/null +++ b/test/e2e/shared/exec_test.go @@ -0,0 +1,93 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "os" + "testing" +) + +// Test_commandsForMachine can be used to develop and test +// commandsForMachine locally. +func Test_commandsForMachine(t *testing.T) { + t.Skip() + + f, err := os.OpenFile("/tmp/test/instance.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + type args struct { + machineIP string + bastionIP string + commands []command + } + tests := []struct { + name string + args args + }{ + { + name: "", + args: args{ + machineIP: "10.6.0.230", + bastionIP: "172.24.4.58", + commands: []command{ + { + title: "systemd", + cmd: "journalctl --no-pager --output=short-precise | grep -v 'audit:\\|audit\\['", + }, + { + title: "kern", + cmd: "journalctl --no-pager --output=short-precise -k", + }, + { + title: "containerd-info", + cmd: "crictl info", + }, + { + title: "containerd-containers", + cmd: "crictl ps", + }, + { + title: "containerd-pods", + cmd: "crictl pods", + }, + { + title: "cloud-final", + cmd: "journalctl --no-pager -u cloud-final", + }, + { + title: "kubelet", + cmd: "journalctl --no-pager -u kubelet.service", + }, + { + title: "containerd", + cmd: "journalctl --no-pager -u containerd.service", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + commandsForMachine(f, tt.args.machineIP, tt.args.bastionIP, tt.args.commands) + }) + } +} diff --git a/test/e2e/shared/openstack.go b/test/e2e/shared/openstack.go new file mode 100644 index 0000000000..47110fc78c --- /dev/null +++ b/test/e2e/shared/openstack.go @@ -0,0 +1,236 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "os" + "path" + "path/filepath" + "strings" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" + "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" + "github.com/gophercloud/utils/openstack/clientconfig" + "gopkg.in/ini.v1" + "sigs.k8s.io/yaml" + + "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/provider" +) + +// ensureSSHKeyPair ensures A SSH key is present under the name +func ensureSSHKeyPair(openStackCloudYAMLFile, cloudName, keyPairName string) { + Byf("Ensuring presence of SSH key in OpenStack: key-name=%s", keyPairName) + + clouds := getParsedOpenStackCloudYAML(openStackCloudYAMLFile) + cloud := clouds.Clouds[cloudName] + + providerClient, clientOpts, err := provider.NewClient(cloud, nil) + Expect(err).NotTo(HaveOccurred()) + + computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{Region: clientOpts.RegionName}) + Expect(err).NotTo(HaveOccurred()) + + keyPairCreateOpts := &keypairs.CreateOpts{ + Name: keyPairName, + } + _, err = keypairs.Create(computeClient, keyPairCreateOpts).Extract() + if err != nil && !strings.Contains(err.Error(), "already exists") { + Expect(err).NotTo(HaveOccurred()) + } +} + +func DumpOpenStackClusters(_ context.Context, e2eCtx *E2EContext, bootstrapClusterProxyName string) { + By("Running DumpOpenStackClusters") + logPath := filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", bootstrapClusterProxyName, "openstack-resources") + if err := os.MkdirAll(logPath, os.ModePerm); err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "error creating directory %s: %s\n", logPath, err) + return + } + _, _ = fmt.Fprintf(GinkgoWriter, "folder created for OpenStack clusters: %s\n", logPath) + + providerClient, clientOpts, err := getProviderClient(e2eCtx) + if err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "error creating provider client: %s\n", err) + return + } + + if err := dumpOpenStackServers(providerClient, clientOpts, logPath); err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "error dumping OpenStack server: %s\n", err) + } + + if err := dumpOpenStackImages(providerClient, clientOpts, logPath); err != nil { + _, _ = fmt.Fprintf(GinkgoWriter, "error dumping OpenStack images: %s\n", err) + } +} + +func dumpOpenStackServers(providerClient *gophercloud.ProviderClient, clientOpts *clientconfig.ClientOpts, logPath string) error { + computeClient, err := openstack.NewComputeV2(providerClient, gophercloud.EndpointOpts{ + Region: clientOpts.RegionName, + }) + if err != nil { + return fmt.Errorf("error creating compute client: %s", err) + } + + allPages, err := servers.List(computeClient, servers.ListOpts{}).AllPages() + if err != nil { + return fmt.Errorf("error getting server: %s", err) + } + serverList, err := servers.ExtractServers(allPages) + if err != nil { + return fmt.Errorf("error extracting server: %s", err) + } + serverJSON, err := json.MarshalIndent(serverList, "", " ") + if err != nil { + return fmt.Errorf("error marshalling server %v: %s", serverList, err) + } + if err := os.WriteFile(path.Join(logPath, "server.txt"), serverJSON, 0o600); err != nil { + return fmt.Errorf("error writing severJSON %s: %s", serverJSON, err) + } + return nil +} + +func dumpOpenStackImages(providerClient *gophercloud.ProviderClient, clientOpts *clientconfig.ClientOpts, logPath string) error { + imageClient, err := openstack.NewImageServiceV2(providerClient, gophercloud.EndpointOpts{ + Region: clientOpts.RegionName, + }) + if err != nil { + return fmt.Errorf("error creating compute client: %s", err) + } + + allPages, err := images.List(imageClient, images.ListOpts{}).AllPages() + if err != nil { + return fmt.Errorf("error getting images: %s", err) + } + imagesList, err := images.ExtractImages(allPages) + if err != nil { + return fmt.Errorf("error extracting images: %s", err) + } + imagesJSON, err := json.MarshalIndent(imagesList, "", " ") + if err != nil { + return fmt.Errorf("error marshalling images %v: %s", imagesList, err) + } + if err := os.WriteFile(path.Join(logPath, "images.txt"), imagesJSON, 0o600); err != nil { + return fmt.Errorf("error writing seversJSON %s: %s", imagesJSON, err) + } + return nil +} + +func getProviderClient(e2eCtx *E2EContext) (*gophercloud.ProviderClient, *clientconfig.ClientOpts, error) { + openStackCloudYAMLFile := e2eCtx.E2EConfig.GetVariable(OpenStackCloudYAMLFile) + openstackCloud := e2eCtx.E2EConfig.GetVariable(OpenStackCloud) + + clouds := getParsedOpenStackCloudYAML(openStackCloudYAMLFile) + cloud := clouds.Clouds[openstackCloud] + + providerClient, clientOpts, err := provider.NewClient(cloud, nil) + if err != nil { + return nil, nil, err + } + + return providerClient, clientOpts, nil +} + +// Config is used to read and store information from the cloud configuration file +// Depends on: /home/sbuerin/code/src/k8s.io/cloud-provider-openstack/pkg/cloudprovider/providers/openstack/openstack.go +type Config struct { + Global AuthOpts +} + +type AuthOpts struct { + AuthURL string `ini:"auth-url"` + UserID string `ini:"user-id"` + Username string `ini:"username"` + Password string `ini:"password"` + TenantID string `ini:"tenant-id"` + TenantName string `ini:"tenant-name"` + DomainID string `ini:"domain-id"` + DomainName string `ini:"domain-name"` + //TenantDomainID string `ini:"tenant-domain-id"` + //TenantDomainName string `ini:"tenant-domain-name"` + //UserDomainID string `ini:"user-domain-id"` + //UserDomainName string `ini:"user-domain-name"` + Region string `ini:"region"` + CAFile string `ini:"ca-file"` + //TLSInsecure string `ini:"tls-insecure"` + + //CloudsFile string `ini:"clouds-file"` + //Cloud string `ini:"cloud"` + + //ApplicationCredentialID string `ini:"application-credential-id"` + //ApplicationCredentialName string `ini:"application-credential-name"` +} + +func getEncodedOpenStackCloudYAML(cloudYAML string) string { + cloudYAMLContent := getOpenStackCloudYAML(cloudYAML) + return base64.StdEncoding.EncodeToString(cloudYAMLContent) +} + +func getEncodedOpenStackCloudProviderConf(cloudYAML, cloudName string) string { + clouds := getParsedOpenStackCloudYAML(cloudYAML) + cloud := clouds.Clouds[cloudName] + cloudProviderConf := &Config{ + Global: AuthOpts{ + AuthURL: cloud.AuthInfo.AuthURL, + UserID: cloud.AuthInfo.UserID, + Username: cloud.AuthInfo.Username, + Password: cloud.AuthInfo.Password, + TenantID: cloud.AuthInfo.ProjectID, + TenantName: cloud.AuthInfo.ProjectName, + DomainID: cloud.AuthInfo.DomainID, + DomainName: cloud.AuthInfo.DomainName, + Region: cloud.RegionName, + }, + } + + cfg := ini.Empty() + err := ini.ReflectFrom(cfg, cloudProviderConf) + Expect(err).NotTo(HaveOccurred()) + + var buf bytes.Buffer + _, err = cfg.WriteTo(&buf) + Expect(err).NotTo(HaveOccurred()) + + return base64.StdEncoding.EncodeToString(buf.Bytes()) +} + +func getParsedOpenStackCloudYAML(cloudYAML string) clientconfig.Clouds { + cloudYAMLContent := getOpenStackCloudYAML(cloudYAML) + + var clouds clientconfig.Clouds + err := yaml.Unmarshal(cloudYAMLContent, &clouds) + Expect(err).NotTo(HaveOccurred()) + return clouds +} + +func getOpenStackCloudYAML(cloudYAML string) []byte { + cloudYAMLContent, err := os.ReadFile(cloudYAML) + Expect(err).NotTo(HaveOccurred()) + return cloudYAMLContent +} diff --git a/test/e2e/shared/openstack_test.go b/test/e2e/shared/openstack_test.go new file mode 100644 index 0000000000..28de1e43dd --- /dev/null +++ b/test/e2e/shared/openstack_test.go @@ -0,0 +1,55 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "context" + "fmt" + "os" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "sigs.k8s.io/cluster-api/test/framework/clusterctl" +) + +// Test_dumpOpenStackClusters can be used to develop and test +// dumpOpenStackClusters locally. +func Test_dumpOpenStackClusters(t *testing.T) { + t.Skip() + RegisterFailHandler(Fail) + + currentDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + DumpOpenStackClusters(context.TODO(), &E2EContext{ + E2EConfig: &clusterctl.E2EConfig{ + Variables: map[string]string{ + OpenStackCloudYAMLFile: fmt.Sprintf("%s/../../../clouds.yaml", currentDir), + OpenStackCloud: "capo-e2e", + }, + }, + Settings: Settings{ + ArtifactFolder: "/tmp", + }, + }, "bootstrap") +} diff --git a/test/e2e/shared/suite.go b/test/e2e/shared/suite.go new file mode 100644 index 0000000000..96543705d8 --- /dev/null +++ b/test/e2e/shared/suite.go @@ -0,0 +1,216 @@ +// +build e2e + +/* +Copyright 2021 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 shared + +import ( + "context" + "flag" + "io/ioutil" + "os" + "path/filepath" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "sigs.k8s.io/cluster-api/test/framework" + "sigs.k8s.io/cluster-api/test/framework/clusterctl" + "sigs.k8s.io/yaml" +) + +type synchronizedBeforeTestSuiteConfig struct { + ArtifactFolder string `json:"artifactFolder,omitempty"` + ConfigPath string `json:"configPath,omitempty"` + ClusterctlConfigPath string `json:"clusterctlConfigPath,omitempty"` + KubeconfigPath string `json:"kubeconfigPath,omitempty"` + E2EConfig clusterctl.E2EConfig `json:"e2eConfig,omitempty"` + KubetestConfigFilePath string `json:"kubetestConfigFilePath,omitempty"` + UseCIArtifacts bool `json:"useCIArtifacts,omitempty"` + GinkgoNodes int `json:"ginkgoNodes,omitempty"` + GinkgoSlowSpecThreshold int `json:"ginkgoSlowSpecThreshold,omitempty"` +} + +// Node1BeforeSuite is the common setup down on the first ginkgo node before the test suite runs +func Node1BeforeSuite(e2eCtx *E2EContext) []byte { + By("Running Node1BeforeSuite") + + flag.Parse() + Expect(e2eCtx.Settings.ConfigPath).To(BeAnExistingFile(), "Invalid test suite argument. configPath should be an existing file.") + Expect(os.MkdirAll(e2eCtx.Settings.ArtifactFolder, 0o750)).To(Succeed(), "Invalid test suite argument. Can't create artifacts-folder %q", e2eCtx.Settings.ArtifactFolder) + Byf("Loading the e2e test configuration from %q", e2eCtx.Settings.ConfigPath) + e2eCtx.E2EConfig = LoadE2EConfig(e2eCtx.Settings.ConfigPath) + sourceTemplate, err := ioutil.ReadFile(filepath.Join(e2eCtx.Settings.DataFolder, e2eCtx.Settings.SourceTemplate)) + Expect(err).NotTo(HaveOccurred()) + + var clusterctlCITemplate clusterctl.Files + + platformKustomization, err := ioutil.ReadFile(filepath.Join(e2eCtx.Settings.DataFolder, "ci-artifacts-platform-kustomization.yaml")) + Expect(err).NotTo(HaveOccurred()) + + // TODO(sbuerin): should be removed after: https://github.com/kubernetes-sigs/kustomize/issues/2825 is fixed + //ciTemplate, err := kubernetesversions.GenerateCIArtifactsInjectedTemplateForDebian( + // kubernetesversions.GenerateCIArtifactsInjectedTemplateForDebianInput{ + // ArtifactsDirectory: e2eCtx.Settings.ArtifactFolder, + // SourceTemplate: sourceTemplate, + // PlatformKustomization: platformKustomization, + // }, + //) + ciTemplate, err := GenerateCIArtifactsInjectedTemplateForDebian( + GenerateCIArtifactsInjectedTemplateForDebianInput{ + ArtifactsDirectory: e2eCtx.Settings.ArtifactFolder, + SourceTemplate: sourceTemplate, + PlatformKustomization: platformKustomization, + }, + ) + Expect(err).NotTo(HaveOccurred()) + + clusterctlCITemplate = clusterctl.Files{ + SourcePath: ciTemplate, + TargetName: "cluster-template-conformance-ci-artifacts.yaml", + } + + providers := e2eCtx.E2EConfig.Providers + for i, prov := range providers { + if prov.Name != "openstack" { + continue + } + e2eCtx.E2EConfig.Providers[i].Files = append(e2eCtx.E2EConfig.Providers[i].Files, clusterctlCITemplate) + } + + openStackCloudYAMLFile := e2eCtx.E2EConfig.GetVariable(OpenStackCloudYAMLFile) + openStackCloud := e2eCtx.E2EConfig.GetVariable(OpenStackCloud) + ensureSSHKeyPair(openStackCloudYAMLFile, openStackCloud, DefaultSSHKeyPairName) + + Byf("Creating a clusterctl local repository into %q", e2eCtx.Settings.ArtifactFolder) + e2eCtx.Environment.ClusterctlConfigPath = createClusterctlLocalRepository(e2eCtx.E2EConfig, filepath.Join(e2eCtx.Settings.ArtifactFolder, "repository")) + + By("Setting up the bootstrap cluster") + e2eCtx.Environment.BootstrapClusterProvider, e2eCtx.Environment.BootstrapClusterProxy = setupBootstrapCluster(e2eCtx.E2EConfig, e2eCtx.Environment.Scheme, e2eCtx.Settings.UseExistingCluster) + + SetEnvVar("OPENSTACK_CLOUD_YAML_B64", getEncodedOpenStackCloudYAML(openStackCloudYAMLFile), true) + SetEnvVar("OPENSTACK_CLOUD_PROVIDER_CONF_B64", getEncodedOpenStackCloudProviderConf(openStackCloudYAMLFile, openStackCloud), true) + + By("Initializing the bootstrap cluster") + initBootstrapCluster(e2eCtx) + + conf := synchronizedBeforeTestSuiteConfig{ + ArtifactFolder: e2eCtx.Settings.ArtifactFolder, + ConfigPath: e2eCtx.Settings.ConfigPath, + ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, + KubeconfigPath: e2eCtx.Environment.BootstrapClusterProxy.GetKubeconfigPath(), + E2EConfig: *e2eCtx.E2EConfig, + KubetestConfigFilePath: e2eCtx.Settings.KubetestConfigFilePath, + UseCIArtifacts: e2eCtx.Settings.UseCIArtifacts, + GinkgoNodes: e2eCtx.Settings.GinkgoNodes, + GinkgoSlowSpecThreshold: e2eCtx.Settings.GinkgoSlowSpecThreshold, + } + + data, err := yaml.Marshal(conf) + Expect(err).NotTo(HaveOccurred()) + return data +} + +// AllNodesBeforeSuite is the common setup down on each ginkgo parallel node before the test suite runs +func AllNodesBeforeSuite(e2eCtx *E2EContext, data []byte) { + By("Running AllNodesBeforeSuite") + + conf := &synchronizedBeforeTestSuiteConfig{} + err := yaml.UnmarshalStrict(data, conf) + Expect(err).NotTo(HaveOccurred()) + e2eCtx.Settings.ArtifactFolder = conf.ArtifactFolder + e2eCtx.Settings.ConfigPath = conf.ConfigPath + e2eCtx.Environment.ClusterctlConfigPath = conf.ClusterctlConfigPath + e2eCtx.Environment.BootstrapClusterProxy = framework.NewClusterProxy("bootstrap", conf.KubeconfigPath, e2eCtx.Environment.Scheme) + e2eCtx.E2EConfig = &conf.E2EConfig + e2eCtx.Settings.KubetestConfigFilePath = conf.KubetestConfigFilePath + e2eCtx.Settings.UseCIArtifacts = conf.UseCIArtifacts + e2eCtx.Settings.GinkgoNodes = conf.GinkgoNodes + e2eCtx.Settings.GinkgoSlowSpecThreshold = conf.GinkgoSlowSpecThreshold + + SetEnvVar("OPENSTACK_SSH_KEY_NAME", DefaultSSHKeyPairName, false) + + e2eCtx.Environment.ResourceTicker = time.NewTicker(time.Second * 5) + e2eCtx.Environment.ResourceTickerDone = make(chan bool) + // Get OpenStack server logs every 5 minutes + e2eCtx.Environment.MachineTicker = time.NewTicker(time.Second * 300) + e2eCtx.Environment.MachineTickerDone = make(chan bool) + resourceCtx, resourceCancel := context.WithCancel(context.Background()) + machineCtx, machineCancel := context.WithCancel(context.Background()) + + // Dump resources every 5 seconds + go func() { + defer GinkgoRecover() + for { + select { + case <-e2eCtx.Environment.ResourceTickerDone: + resourceCancel() + return + case <-e2eCtx.Environment.ResourceTicker.C: + for k := range e2eCtx.Environment.Namespaces { + DumpSpecResources(resourceCtx, e2eCtx, k) + } + } + } + }() + + // Dump machine logs every 60 seconds + go func() { + defer GinkgoRecover() + for { + select { + case <-e2eCtx.Environment.MachineTickerDone: + machineCancel() + return + case <-e2eCtx.Environment.MachineTicker.C: + for k := range e2eCtx.Environment.Namespaces { + DumpMachines(machineCtx, e2eCtx, k) + } + } + } + }() +} + +// Node1AfterSuite is cleanup that runs on the first ginkgo node after the test suite finishes +func Node1AfterSuite(e2eCtx *E2EContext) { + By("Running Node1AfterSuite") + + if e2eCtx.Environment.ResourceTickerDone != nil { + e2eCtx.Environment.ResourceTickerDone <- true + } + if e2eCtx.Environment.MachineTickerDone != nil { + e2eCtx.Environment.MachineTickerDone <- true + } + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Minute) + defer cancel() + DumpOpenStackClusters(ctx, e2eCtx, e2eCtx.Environment.BootstrapClusterProxy.GetName()) + for k := range e2eCtx.Environment.Namespaces { + DumpSpecResourcesAndCleanup(ctx, "", k, e2eCtx) + DumpMachines(ctx, e2eCtx, k) + } +} + +// AllNodesAfterSuite is cleanup that runs on all ginkgo parallel nodes after the test suite finishes +func AllNodesAfterSuite(e2eCtx *E2EContext) { + By("Running AllNodesAfterSuite") + + By("Tearing down the management cluster") + if !e2eCtx.Settings.SkipCleanup { + tearDown(e2eCtx.Environment.BootstrapClusterProvider, e2eCtx.Environment.BootstrapClusterProxy) + } +} diff --git a/test/e2e/shared/tmp_template.go b/test/e2e/shared/tmp_template.go new file mode 100644 index 0000000000..72807f907c --- /dev/null +++ b/test/e2e/shared/tmp_template.go @@ -0,0 +1,109 @@ +/* +Copyright 2021 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. +*/ + +// TODO(sbuerin): should be removed after: https://github.com/kubernetes-sigs/kustomize/issues/2825 is fixed +// copied from: cluster-api/test/framework/kubernetesversions/template.go +// currently we have to skip the CAPI generated debian patch because it would overwrite our files + +package shared + +import ( + "errors" + "io/ioutil" + "os" + "os/exec" + "path" + + "sigs.k8s.io/cluster-api/test/framework" +) + +type GenerateCIArtifactsInjectedTemplateForDebianInput struct { + // ArtifactsDirectory is where conformance suite output will go. Defaults to _artifacts + ArtifactsDirectory string + // SourceTemplate is an input YAML clusterctl template which is to have + // the CI artifact script injection + SourceTemplate []byte + // PlatformKustomization is an SMP (strategic-merge-style) patch for adding + // platform specific kustomizations required for use with CI, such as + // referencing a specific image + PlatformKustomization []byte + // KubeadmConfigTemplateName is the name of the KubeadmConfigTemplate resource + // that needs to have the Debian install script injected. Defaults to "${CLUSTER_NAME}-md-0". + KubeadmConfigTemplateName string + // KubeadmControlPlaneName is the name of the KubeadmControlPlane resource + // that needs to have the Debian install script injected. Defaults to "${CLUSTER_NAME}-control-plane". + KubeadmControlPlaneName string + // KubeadmConfigName is the name of a KubeadmConfig that needs kustomizing. To be used in conjunction with MachinePools. Optional. + KubeadmConfigName string +} + +// GenerateCIArtifactsInjectedTemplateForDebian takes a source clusterctl template +// and a platform-specific Kustomize SMP patch and injects a bash script to download +// and install the debian packages for the given Kubernetes version, returning the +// location of the outputted file. +func GenerateCIArtifactsInjectedTemplateForDebian(input GenerateCIArtifactsInjectedTemplateForDebianInput) (string, error) { + if input.SourceTemplate == nil { + return "", errors.New("SourceTemplate must be provided") + } + input.ArtifactsDirectory = framework.ResolveArtifactsDirectory(input.ArtifactsDirectory) + if input.KubeadmConfigTemplateName == "" { + input.KubeadmConfigTemplateName = "${CLUSTER_NAME}-md-0" + } + if input.KubeadmControlPlaneName == "" { + input.KubeadmControlPlaneName = "${CLUSTER_NAME}-control-plane" + } + templateDir := path.Join(input.ArtifactsDirectory, "templates") + overlayDir := path.Join(input.ArtifactsDirectory, "overlay") + + if err := os.MkdirAll(templateDir, 0o750); err != nil { + return "", err + } + if err := os.MkdirAll(overlayDir, 0o750); err != nil { + return "", err + } + + kustomizedTemplate := path.Join(templateDir, "cluster-template-conformance-ci-artifacts.yaml") + + kustomization := []byte(` +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: default +resources: + - ci-artifacts-source-template.yaml +patchesStrategicMerge: + - platform-kustomization.yaml +`) + + if err := ioutil.WriteFile(path.Join(overlayDir, "kustomization.yaml"), kustomization, 0o600); err != nil { + return "", err + } + + if err := ioutil.WriteFile(path.Join(overlayDir, "ci-artifacts-source-template.yaml"), input.SourceTemplate, 0o600); err != nil { + return "", err + } + if err := ioutil.WriteFile(path.Join(overlayDir, "platform-kustomization.yaml"), input.PlatformKustomization, 0o600); err != nil { + return "", err + } + cmd := exec.Command("kustomize", "build", overlayDir) + data, err := cmd.CombinedOutput() + if err != nil { + return "", err + } + if err := ioutil.WriteFile(kustomizedTemplate, data, 0o600); err != nil { + return "", err + } + return kustomizedTemplate, nil +} diff --git a/test/e2e/suites/conformance/conformance_suite_test.go b/test/e2e/suites/conformance/conformance_suite_test.go new file mode 100644 index 0000000000..8fa7a7d8c1 --- /dev/null +++ b/test/e2e/suites/conformance/conformance_suite_test.go @@ -0,0 +1,55 @@ +// +build e2e + +/* +Copyright 2021 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 conformance + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared" + "sigs.k8s.io/cluster-api/test/framework" +) + +var ( + e2eCtx *shared.E2EContext +) + +func init() { + e2eCtx = shared.NewE2EContext() + shared.CreateDefaultFlags(e2eCtx) +} + +func TestE2EConformance(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecsWithDefaultAndCustomReporters(t, "capo-e2e-conformance", []Reporter{framework.CreateJUnitReporterForProw(e2eCtx.Settings.ArtifactFolder)}) +} + +var _ = SynchronizedBeforeSuite(func() []byte { + return shared.Node1BeforeSuite(e2eCtx) +}, func(data []byte) { + shared.AllNodesBeforeSuite(e2eCtx, data) +}) + +var _ = SynchronizedAfterSuite(func() { + shared.Node1AfterSuite(e2eCtx) +}, func() { + shared.AllNodesAfterSuite(e2eCtx) +}) diff --git a/test/e2e/suites/conformance/conformance_test.go b/test/e2e/suites/conformance/conformance_test.go new file mode 100644 index 0000000000..a932dfc486 --- /dev/null +++ b/test/e2e/suites/conformance/conformance_test.go @@ -0,0 +1,120 @@ +// +build e2e + +/* +Copyright 2021 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 conformance + +import ( + "context" + "fmt" + "path/filepath" + "strconv" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" + "sigs.k8s.io/cluster-api/test/framework/clusterctl" + "sigs.k8s.io/cluster-api/test/framework/kubernetesversions" + "sigs.k8s.io/cluster-api/test/framework/kubetest" + "sigs.k8s.io/cluster-api/util" + + "sigs.k8s.io/cluster-api-provider-openstack/test/e2e/shared" +) + +var _ = Describe("conformance tests", func() { + var ( + namespace *corev1.Namespace + ctx context.Context + specName = "conformance" + ) + + BeforeEach(func() { + Expect(e2eCtx.Environment.BootstrapClusterProxy).ToNot(BeNil(), "Invalid argument. BootstrapClusterProxy can't be nil") + Expect(e2eCtx.E2EConfig).ToNot(BeNil(), "Invalid argument. e2eConfig can't be nil when calling %s spec", specName) + Expect(e2eCtx.E2EConfig.Variables).To(HaveKey(shared.KubernetesVersion)) + ctx = context.TODO() + // Setup a Namespace where to host objects for this spec and create a watcher for the namespace events. + namespace = shared.SetupSpecNamespace(ctx, specName, e2eCtx) + }) + Measure(specName, func(b Benchmarker) { + + name := fmt.Sprintf("cluster-%s", util.RandomString(6)) + shared.SetEnvVar("USE_CI_ARTIFACTS", "true", false) + kubernetesVersion := e2eCtx.E2EConfig.GetVariable(shared.KubernetesVersion) + flavor := clusterctl.DefaultFlavor + + // TODO(sbuerin): we always need ci artifacts, because we don't have images for every Kubernetes version + // * we're using ci-artifacts of the release we want and + // * with UseCIArtifacts we use the latest Kubernetes ci release + //if e2eCtx.Settings.UseCIArtifacts { + flavor = "conformance-ci-artifacts" + if e2eCtx.Settings.UseCIArtifacts { + var err error + kubernetesVersion, err = kubernetesversions.LatestCIRelease() + Expect(err).NotTo(HaveOccurred()) + } + + workerMachineCount, err := strconv.ParseInt(e2eCtx.E2EConfig.GetVariable("CONFORMANCE_WORKER_MACHINE_COUNT"), 10, 64) + Expect(err).NotTo(HaveOccurred()) + controlPlaneMachineCount, err := strconv.ParseInt(e2eCtx.E2EConfig.GetVariable("CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT"), 10, 64) + Expect(err).NotTo(HaveOccurred()) + + b.Time("cluster creation", func() { + result := &clusterctl.ApplyClusterTemplateAndWaitResult{} + clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{ + ClusterProxy: e2eCtx.Environment.BootstrapClusterProxy, + ConfigCluster: clusterctl.ConfigClusterInput{ + LogFolder: filepath.Join(e2eCtx.Settings.ArtifactFolder, "clusters", e2eCtx.Environment.BootstrapClusterProxy.GetName()), + ClusterctlConfigPath: e2eCtx.Environment.ClusterctlConfigPath, + KubeconfigPath: e2eCtx.Environment.BootstrapClusterProxy.GetKubeconfigPath(), + InfrastructureProvider: clusterctl.DefaultInfrastructureProvider, + Flavor: flavor, + Namespace: namespace.Name, + ClusterName: name, + KubernetesVersion: kubernetesVersion, + ControlPlaneMachineCount: pointer.Int64Ptr(controlPlaneMachineCount), + WorkerMachineCount: pointer.Int64Ptr(workerMachineCount), + }, + WaitForClusterIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-cluster"), + WaitForControlPlaneIntervals: e2eCtx.E2EConfig.GetIntervals(specName, "wait-control-plane"), + WaitForMachineDeployments: e2eCtx.E2EConfig.GetIntervals(specName, "wait-worker-nodes"), + }, result) + }) + + workloadProxy := e2eCtx.Environment.BootstrapClusterProxy.GetWorkloadCluster(ctx, namespace.Name, name) + b.Time("conformance suite", func() { + err := kubetest.Run(ctx, + kubetest.RunInput{ + ClusterProxy: workloadProxy, + NumberOfNodes: int(workerMachineCount), + ConfigFilePath: e2eCtx.Settings.KubetestConfigFilePath, + GinkgoNodes: 5, + }, + ) + Expect(err).To(BeNil(), "error on kubetest execution") + }) + }, 1) + + AfterEach(func() { + shared.SetEnvVar("USE_CI_ARTIFACTS", "false", false) + // Dumps all the resources in the spec namespace, then cleanups the cluster object and the spec namespace itself. + shared.DumpSpecResourcesAndCleanup(ctx, "", namespace, e2eCtx) + }) + +}) diff --git a/versions.mk b/versions.mk new file mode 100644 index 0000000000..6687394fe2 --- /dev/null +++ b/versions.mk @@ -0,0 +1,15 @@ +# Copyright 2021 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. + +GOLANG_VERSION := 1.16.0