From 7bf8b5361f280da3e56fdba91f0549833ae50e7b Mon Sep 17 00:00:00 2001 From: Joshua Sprey Date: Wed, 11 Jan 2023 15:22:14 +0100 Subject: [PATCH 01/37] Add initial backup operator. --- .env.template | 11 + .gitignore | 26 +- CHANGELOG.md | 7 + Dockerfile | 47 + Jenkinsfile | 244 +++ Makefile | 83 + PROJECT | 16 + README.md | 18 +- build/.editorconfig | 2 + build/.gitignore | 2 + build/make/bats.mk | 64 + build/make/bats/Dockerfile | 7 + build/make/bats/customBatsEntrypoint.sh | 6 + build/make/bower.mk | 28 + build/make/build.mk | 51 + build/make/clean.mk | 15 + build/make/dependencies-gomod.mk | 8 + build/make/deploy-debian.mk | 65 + build/make/digital-signature.mk | 24 + build/make/k8s-controller.mk | 96 + build/make/k8s-dogu.mk | 44 + build/make/k8s-dogu.tpl | 9 + build/make/k8s.mk | 124 ++ build/make/package-debian.mk | 79 + build/make/package-tar.mk | 10 + build/make/release.mk | 11 + build/make/release.sh | 54 + build/make/release_functions.sh | 220 +++ build/make/self-update.mk | 22 + build/make/static-analysis.mk | 66 + build/make/test-common.mk | 6 + build/make/test-integration.mk | 49 + build/make/test-unit.mk | 36 + build/make/variables.mk | 93 + build/make/yarn.mk | 27 + config/default/kustomization.yaml | 70 + config/default/manager_auth_proxy_patch.yaml | 33 + config/default/manager_config_patch.yaml | 19 + config/manager/controller_manager_config.yaml | 11 + config/manager/kustomization.yaml | 14 + config/manager/manager.yaml | 90 + config/prometheus/kustomization.yaml | 2 + config/prometheus/monitor.yaml | 20 + .../rbac/auth_proxy_client_clusterrole.yaml | 9 + config/rbac/auth_proxy_role.yaml | 17 + config/rbac/auth_proxy_role_binding.yaml | 11 + config/rbac/auth_proxy_service.yaml | 14 + config/rbac/cluster_role.yaml | 16 + config/rbac/cluster_role_binding.yaml | 15 + config/rbac/dogu_editor_role.yaml | 24 + config/rbac/dogu_viewer_role.yaml | 20 + config/rbac/kustomization.yaml | 20 + config/rbac/leader_election_role.yaml | 37 + config/rbac/leader_election_role_binding.yaml | 11 + config/rbac/role.yaml | 12 + config/rbac/role_binding.yaml | 11 + config/rbac/service_account.yaml | 4 + config/samples/cas_config.sh | 10 + .../hallowelt/bluespice-pdfrenderer.yaml | 12 + config/samples/hallowelt/bluespice.yaml | 12 + config/samples/hallowelt/drawio.yaml | 12 + config/samples/itz-bund/teamscale.yaml | 12 + config/samples/k8s/nginx-ingress.yaml | 12 + config/samples/k8s/nginx-static.yaml | 12 + config/samples/k8s_v1_dogu.yaml | 8 + config/samples/ldap-mapper.sh | 3 + config/samples/ldap_config.sh | 2 + config/samples/official/backup.yaml | 12 + config/samples/official/cas.yaml | 12 + config/samples/official/cas_config.sh | 10 + config/samples/official/cockpit.yaml | 12 + config/samples/official/elasticsearch.yaml | 12 + config/samples/official/gotenberg.yaml | 12 + config/samples/official/jenkins.yaml | 12 + config/samples/official/ldap-mapper.sh | 3 + config/samples/official/ldap-mapper.yaml | 12 + config/samples/official/ldap.yaml | 12 + config/samples/official/ldap_config.sh | 2 + config/samples/official/mysql.yaml | 12 + config/samples/official/nexus.yaml | 12 + config/samples/official/plantuml.yaml | 12 + config/samples/official/postfix.yaml | 14 + config/samples/official/postfix_config.sh | 1 + config/samples/official/postgresql.yaml | 14 + config/samples/official/redis.yaml | 12 + config/samples/official/redmine.yaml | 12 + config/samples/official/scm.yaml | 13 + config/samples/official/smeagol.yaml | 12 + config/samples/official/sonar.yaml | 12 + config/samples/official/swaggerui.yaml | 12 + config/samples/official/usermgt.yaml | 14 + config/samples/postfix_config.sh | 1 + config/samples/premium/admin.yaml | 12 + config/samples/premium/confluence.yaml | 12 + config/samples/premium/jira.yaml | 12 + go.mod | 107 ++ go.sum | 1588 +++++++++++++++++ hack/boilerplate.go.txt | 3 + main.go | 149 ++ main_internal_test.go | 165 ++ pkg/config/config.go | 78 + pkg/config/config_test.go | 36 + pkg/controllers/backupController.go | 40 + pkg/logging/logger.go | 118 ++ pkg/logging/logger_test.go | 179 ++ pkg/mocks/external/Client.go | 225 +++ pkg/mocks/external/EventRecorder.go | 50 + pkg/mocks/external/LogSink.go | 97 + pkg/mocks/external/Manager.go | 324 ++++ pkg/mocks/external/StatusWriter.go | 73 + pkg/mocks/external/external.go | 3 + release_args.sh | 20 + sonar-project.properties | 14 + 113 files changed, 5807 insertions(+), 7 deletions(-) create mode 100644 .env.template create mode 100644 CHANGELOG.md create mode 100644 Dockerfile create mode 100644 Jenkinsfile create mode 100644 Makefile create mode 100644 PROJECT create mode 100644 build/.editorconfig create mode 100644 build/.gitignore create mode 100644 build/make/bats.mk create mode 100644 build/make/bats/Dockerfile create mode 100755 build/make/bats/customBatsEntrypoint.sh create mode 100644 build/make/bower.mk create mode 100644 build/make/build.mk create mode 100644 build/make/clean.mk create mode 100644 build/make/dependencies-gomod.mk create mode 100644 build/make/deploy-debian.mk create mode 100644 build/make/digital-signature.mk create mode 100644 build/make/k8s-controller.mk create mode 100644 build/make/k8s-dogu.mk create mode 100644 build/make/k8s-dogu.tpl create mode 100644 build/make/k8s.mk create mode 100644 build/make/package-debian.mk create mode 100644 build/make/package-tar.mk create mode 100644 build/make/release.mk create mode 100755 build/make/release.sh create mode 100755 build/make/release_functions.sh create mode 100644 build/make/self-update.mk create mode 100644 build/make/static-analysis.mk create mode 100644 build/make/test-common.mk create mode 100644 build/make/test-integration.mk create mode 100644 build/make/test-unit.mk create mode 100644 build/make/variables.mk create mode 100644 build/make/yarn.mk create mode 100644 config/default/kustomization.yaml create mode 100644 config/default/manager_auth_proxy_patch.yaml create mode 100644 config/default/manager_config_patch.yaml create mode 100644 config/manager/controller_manager_config.yaml create mode 100644 config/manager/kustomization.yaml create mode 100644 config/manager/manager.yaml create mode 100644 config/prometheus/kustomization.yaml create mode 100644 config/prometheus/monitor.yaml create mode 100644 config/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 config/rbac/auth_proxy_role.yaml create mode 100644 config/rbac/auth_proxy_role_binding.yaml create mode 100644 config/rbac/auth_proxy_service.yaml create mode 100644 config/rbac/cluster_role.yaml create mode 100644 config/rbac/cluster_role_binding.yaml create mode 100644 config/rbac/dogu_editor_role.yaml create mode 100644 config/rbac/dogu_viewer_role.yaml create mode 100644 config/rbac/kustomization.yaml create mode 100644 config/rbac/leader_election_role.yaml create mode 100644 config/rbac/leader_election_role_binding.yaml create mode 100644 config/rbac/role.yaml create mode 100644 config/rbac/role_binding.yaml create mode 100644 config/rbac/service_account.yaml create mode 100644 config/samples/cas_config.sh create mode 100644 config/samples/hallowelt/bluespice-pdfrenderer.yaml create mode 100644 config/samples/hallowelt/bluespice.yaml create mode 100644 config/samples/hallowelt/drawio.yaml create mode 100644 config/samples/itz-bund/teamscale.yaml create mode 100644 config/samples/k8s/nginx-ingress.yaml create mode 100644 config/samples/k8s/nginx-static.yaml create mode 100644 config/samples/k8s_v1_dogu.yaml create mode 100644 config/samples/ldap-mapper.sh create mode 100644 config/samples/ldap_config.sh create mode 100644 config/samples/official/backup.yaml create mode 100644 config/samples/official/cas.yaml create mode 100755 config/samples/official/cas_config.sh create mode 100644 config/samples/official/cockpit.yaml create mode 100644 config/samples/official/elasticsearch.yaml create mode 100644 config/samples/official/gotenberg.yaml create mode 100644 config/samples/official/jenkins.yaml create mode 100755 config/samples/official/ldap-mapper.sh create mode 100644 config/samples/official/ldap-mapper.yaml create mode 100644 config/samples/official/ldap.yaml create mode 100755 config/samples/official/ldap_config.sh create mode 100644 config/samples/official/mysql.yaml create mode 100644 config/samples/official/nexus.yaml create mode 100644 config/samples/official/plantuml.yaml create mode 100644 config/samples/official/postfix.yaml create mode 100755 config/samples/official/postfix_config.sh create mode 100644 config/samples/official/postgresql.yaml create mode 100644 config/samples/official/redis.yaml create mode 100644 config/samples/official/redmine.yaml create mode 100644 config/samples/official/scm.yaml create mode 100644 config/samples/official/smeagol.yaml create mode 100644 config/samples/official/sonar.yaml create mode 100644 config/samples/official/swaggerui.yaml create mode 100644 config/samples/official/usermgt.yaml create mode 100644 config/samples/postfix_config.sh create mode 100644 config/samples/premium/admin.yaml create mode 100644 config/samples/premium/confluence.yaml create mode 100644 config/samples/premium/jira.yaml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 hack/boilerplate.go.txt create mode 100644 main.go create mode 100644 main_internal_test.go create mode 100644 pkg/config/config.go create mode 100644 pkg/config/config_test.go create mode 100644 pkg/controllers/backupController.go create mode 100644 pkg/logging/logger.go create mode 100644 pkg/logging/logger_test.go create mode 100644 pkg/mocks/external/Client.go create mode 100644 pkg/mocks/external/EventRecorder.go create mode 100644 pkg/mocks/external/LogSink.go create mode 100644 pkg/mocks/external/Manager.go create mode 100644 pkg/mocks/external/StatusWriter.go create mode 100644 pkg/mocks/external/external.go create mode 100644 release_args.sh create mode 100644 sonar-project.properties diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..c148c38 --- /dev/null +++ b/.env.template @@ -0,0 +1,11 @@ +# Usage: +# 1. Copy this file as `.env` into your project +# 2. Adapt the information below with the your personal data. +# 3. INFO: escape special characters like # with \ +# +# The file `.env` is ignored by git. Note: DO NOT COMMIT your personal data. + +# It is necessary to set the stage to `development` when developing locally (optional) +#export STAGE=development +export LOG_LEVEL=debug +export NAMESPACE=$(shell kubectl config view --minify -o jsonpath='{..namespace}') \ No newline at end of file diff --git a/.gitignore b/.gitignore index 66fd13c..b0939ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,29 @@ # Binaries for programs and plugins -*.exe -*.exe~ -*.dll *.so *.dylib +.bin -# Test binary, built with `go test -c` +# Test binary, build with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out +target -# Dependency directories (remove the comment below to include it) -# vendor/ +# Kubernetes Generated files - skip generated files, except for vendored files +!vendor/**/zz_generated.* +vendor + +# editor and IDE paraphernalia +.idea +*.swp +*.swo +.code +*~ + +# ignore personal information +.myenv +.netrc + +# Makefiles +.env \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e613bc0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# k8s-backup-operator Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..adc0125 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Build the manager binary +FROM golang:1.18 as builder + +ENV GOPRIVATE=github.com/cloudogu/cesapp/v5 + +WORKDIR /workspace + +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum + +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY main.go main.go +COPY pkg/ pkg/ + +# Copy .git files as the build process builds the current commit id into the binary via ldflags. +# We removed this entry as changes in the repository makes all cached layers invalid leading to rebuilding all layers. +# TODO resolve COMMIT_ID +#COPY .git .git + +# Copy build files +COPY build build +COPY Makefile Makefile + +# Build +RUN go mod vendor +RUN make compile-generic + +# Use distroless as minimal base image to package the manager binary +# Refer to https://github.com/GoogleContainerTools/distroless for more details +FROM gcr.io/distroless/static:nonroot +LABEL maintainer="hello@cloudogu.com" \ + NAME="k8s-backup-operator" \ + VERSION="0.19.0" + +WORKDIR / +COPY --from=builder /workspace/target/k8s-backup-operator . + +# the linter has a problem with the valid colon-syntax +# dockerfile_lint - ignore +USER 65532:65532 + +ENTRYPOINT ["/k8s-backup-operator"] diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..e40f5b9 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,244 @@ +#!groovy + +@Library(['github.com/cloudogu/dogu-build-lib@v1.6.0', 'github.com/cloudogu/ces-build-lib@1.56.0']) +import com.cloudogu.ces.cesbuildlib.* +import com.cloudogu.ces.dogubuildlib.* + +// Creating necessary git objects +git = new Git(this, "cesmarvin") +git.committerName = 'cesmarvin' +git.committerEmail = 'cesmarvin@cloudogu.com' +gitflow = new GitFlow(this, git) +github = new GitHub(this, git) +changelog = new Changelog(this) +Docker docker = new Docker(this) +gpg = new Gpg(this, docker) +goVersion = "1.18" + +// Configuration of repository +repositoryOwner = "cloudogu" +repositoryName = "k8s-backup-operator" +project = "github.com/${repositoryOwner}/${repositoryName}" + +// Configuration of branches +productionReleaseBranch = "main" +developmentBranch = "develop" +currentBranch = "${env.BRANCH_NAME}" + +node('docker') { + timestamps { + stage('Checkout') { + checkout scm + make 'clean' + } + + stage('Lint') { + lintDockerfile() + } + + new Docker(this) + .image("golang:${goVersion}") + .mountJenkinsUser() + .inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}") + { + stage('Build') { + make 'build-controller' + } + + stage("Unit test") { + make 'unit-test' + junit allowEmptyResults: true, testResults: 'target/unit-tests/*-tests.xml' + } + + stage('k8s-Integration-Test') { + make 'k8s-integration-test' + } + + stage("Review dog analysis") { + stageStaticAnalysisReviewDog() + } + + stage('Generate k8s Resources') { + make 'k8s-create-temporary-resource' + archiveArtifacts 'target/*.yaml' + } + } + + stage("Lint k8s Resources") { + stageLintK8SResources() + } + + stage('SonarQube') { + stageStaticAnalysisSonarQube() + } + + K3d k3d = new K3d(this, "${WORKSPACE}", "${WORKSPACE}/k3d", env.PATH) + + try { + Makefile makefile = new Makefile(this) + String controllerVersion = makefile.getVersion() + + stage('Set up k3d cluster') { + k3d.startK3d() + } + + def imageName + stage('Build & Push Image') { + imageName = k3d.buildAndPushToLocalRegistry("cloudogu/${repositoryName}", controllerVersion) + } + + GString sourceDeploymentYaml = "target/${repositoryName}_${controllerVersion}.yaml" + stage('Update development resources') { + docker.image('mikefarah/yq:4.22.1') + .mountJenkinsUser() + .inside("--volume ${WORKSPACE}:/workdir -w /workdir") { + sh "yq -i '(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.name == \"manager\")).image=\"${imageName}\"' ${sourceDeploymentYaml}" + } + } + + stage('Deploy etcd') { + k3d.kubectl("apply -f https://raw.githubusercontent.com/cloudogu/k8s-etcd/develop/manifests/etcd.yaml") + } + + stage('Wait for etcd to be ready') { + sleep(time: 5, unit: "SECONDS") + k3d.kubectl("wait --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=etcd-0 --timeout=300s") + } + + stage('Deploy Manager') { + k3d.kubectl("apply -f ${sourceDeploymentYaml}") + } + + stage('Wait for Ready Rollout') { + k3d.kubectl("--namespace default wait --for=condition=Ready pods --all") + } + + stageAutomaticRelease() + } finally { + stage('Remove k3d cluster') { + k3d.deleteK3d() + } + } + } +} + +void gitWithCredentials(String command) { + withCredentials([usernamePassword(credentialsId: 'cesmarvin', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) { + sh( + script: "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" " + command, + returnStdout: true + ) + } +} + +void stageLintK8SResources() { + String kubevalImage = "cytopia/kubeval:0.13" + Makefile makefile = new Makefile(this) + String controllerVersion = makefile.getVersion() + + docker + .image(kubevalImage) + .inside("-v ${WORKSPACE}/target:/data -t --entrypoint=") + { + sh "kubeval /data/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" + } +} + +void stageStaticAnalysisReviewDog() { + def commitSha = sh(returnStdout: true, script: 'git rev-parse HEAD').trim() + + withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'sonarqube-gh', usernameVariable: 'USERNAME', passwordVariable: 'REVIEWDOG_GITHUB_API_TOKEN']]) { + withEnv(["CI_PULL_REQUEST=${env.CHANGE_ID}", "CI_COMMIT=${commitSha}", "CI_REPO_OWNER=${repositoryOwner}", "CI_REPO_NAME=${repositoryName}"]) { + make 'static-analysis-ci' + } + } +} + +void stageStaticAnalysisSonarQube() { + def scannerHome = tool name: 'sonar-scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation' + withSonarQubeEnv { + sh "git config 'remote.origin.fetch' '+refs/heads/*:refs/remotes/origin/*'" + gitWithCredentials("fetch --all") + + if (currentBranch == productionReleaseBranch) { + echo "This branch has been detected as the production branch." + sh "${scannerHome}/bin/sonar-scanner -Dsonar.branch.name=${env.BRANCH_NAME}" + } else if (currentBranch == developmentBranch) { + echo "This branch has been detected as the development branch." + sh "${scannerHome}/bin/sonar-scanner -Dsonar.branch.name=${env.BRANCH_NAME}" + } else if (env.CHANGE_TARGET) { + echo "This branch has been detected as a pull request." + sh "${scannerHome}/bin/sonar-scanner -Dsonar.pullrequest.key=${env.CHANGE_ID} -Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} -Dsonar.pullrequest.base=${developmentBranch}" + } else if (currentBranch.startsWith("feature/")) { + echo "This branch has been detected as a feature branch." + sh "${scannerHome}/bin/sonar-scanner -Dsonar.branch.name=${env.BRANCH_NAME}" + } else { + echo "This branch has been detected as a miscellaneous branch." + sh "${scannerHome}/bin/sonar-scanner -Dsonar.branch.name=${env.BRANCH_NAME} " + } + } + timeout(time: 2, unit: 'MINUTES') { // Needed when there is no webhook for example + def qGate = waitForQualityGate() + if (qGate.status != 'OK') { + unstable("Pipeline unstable due to SonarQube quality gate failure") + } + } +} + +void stageAutomaticRelease() { + if (gitflow.isReleaseBranch()) { + String releaseVersion = git.getSimpleBranchName() + String dockerReleaseVersion = releaseVersion.split("v")[1] + + stage('Build & Push Image') { + withCredentials([usernamePassword(credentialsId: 'cesmarvin', + passwordVariable: 'CES_MARVIN_PASSWORD', + usernameVariable: 'CES_MARVIN_USERNAME')]) { + // .netrc is necessary to access private repos + sh "echo \"machine github.com\n" + + "login ${CES_MARVIN_USERNAME}\n" + + "password ${CES_MARVIN_PASSWORD}\" >> ~/.netrc" + } + def dockerImage = docker.build("cloudogu/${repositoryName}:${dockerReleaseVersion}") + sh "rm ~/.netrc" + docker.withRegistry('https://registry.hub.docker.com/', 'dockerHubCredentials') { + dockerImage.push("${dockerReleaseVersion}") + } + } + + stage('Finish Release') { + gitflow.finishRelease(releaseVersion, productionReleaseBranch) + } + + stage('Sign after Release') { + gpg.createSignature() + } + + stage('Regenerate resources for release') { + new Docker(this) + .image("golang:${goVersion}") + .mountJenkinsUser() + .inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}") + { + make 'k8s-create-temporary-resource' + } + } + + stage('Push to Registry') { + Makefile makefile = new Makefile(this) + String controllerVersion = makefile.getVersion() + GString targetOperatorResourceYaml = "target/${repositoryName}_${controllerVersion}.yaml" + + DoguRegistry registry = new DoguRegistry(this) + registry.pushK8sYaml(targetOperatorResourceYaml, repositoryName, "k8s", "${controllerVersion}") + } + + stage('Add Github-Release') { + releaseId = github.createReleaseWithChangelog(releaseVersion, changelog, productionReleaseBranch) + } + } +} + +void make(String makeArgs) { + sh "make ${makeArgs}" +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2c852e1 --- /dev/null +++ b/Makefile @@ -0,0 +1,83 @@ +# Set these to the desired values +ARTIFACT_ID=k8s-backup-operator +VERSION=0.19.0 +## Image URL to use all building/pushing image targets +IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} +IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} +GOTAG?=1.18 +MAKEFILES_VERSION=7.0.1 +LINT_VERSION=v1.45.2 +STAGE?=production + +ADDITIONAL_CLEAN=dist-clean + +include build/make/variables.mk +include build/make/self-update.mk +include build/make/dependencies-gomod.mk +include build/make/build.mk +include build/make/test-common.mk +include build/make/test-unit.mk +include build/make/static-analysis.mk +include build/make/clean.mk +include build/make/digital-signature.mk + +PRE_COMPILE=generate +K8S_PRE_GENERATE_TARGETS=k8s-create-temporary-resource template-dev-only-image-pull-policy + +include build/make/k8s-controller.mk + +.PHONY: build-boot +build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. + +##@ Controller specific targets + +.PHONY: manifests +manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + @echo "Generate manifests..." + @$(CONTROLLER_GEN) rbac:roleName=manager-role webhook paths="./..." + +.PHONY: generate +generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. + @echo "Auto-generate deepcopy functions..." + @$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." + +##@ Deployment + +.PHONY: template-stage +template-stage: + @echo "Setting STAGE env in deployment to ${STAGE}!" + @$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"STAGE\").value)=\"${STAGE}\"" $(K8S_RESOURCE_TEMP_YAML) + +.PHONY: template-log-level +template-log-level: + @echo "Setting LOG_LEVEL env in deployment to ${LOG_LEVEL}!" + @$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"LOG_LEVEL\").value)=\"${LOG_LEVEL}\"" $(K8S_RESOURCE_TEMP_YAML) + +.PHONY: template-dev-only-image-pull-policy +template-dev-only-image-pull-policy: $(BINARY_YQ) + @echo "Setting pull policy to always!" + @$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").imagePullPolicy)=\"Always\"" $(K8S_RESOURCE_TEMP_YAML) + +.PHONY: kill-operator-pod +kill-operator-pod: + @echo "Restarting k8s-backup-operator!" + @kubectl -n ${NAMESPACE} delete pods -l 'app.kubernetes.io/name=k8s-backup-operator' + +##@ Debug + +.PHONY: print-debug-info +print-debug-info: ## Generates indo and the list of environment variables required to start the operator in debug mode. + @echo "The target generates a list of env variables required to start the operator in debug mode. These can be pasted directly into the 'go build' run configuration in IntelliJ to run and debug the operator on-demand." + @echo "STAGE=$(STAGE);LOG_LEVEL=$(LOG_LEVEL);KUBECONFIG=$(KUBECONFIG);NAMESPACE=$(NAMESPACE);DOGU_REGISTRY_ENDPOINT=$(DOGU_REGISTRY_ENDPOINT);DOGU_REGISTRY_USERNAME=$(DOGU_REGISTRY_USERNAME);DOGU_REGISTRY_PASSWORD=$(DOGU_REGISTRY_PASSWORD);DOCKER_REGISTRY={\"auths\":{\"$(docker_registry_server)\":{\"username\":\"$(docker_registry_username)\",\"password\":\"$(docker_registry_password)\",\"email\":\"ignore@me.com\",\"auth\":\"ignoreMe\"}}}" + +##@ Mockery + +MOCKERY_BIN=${UTILITY_BIN_PATH}/mockery +MOCKERY_VERSION=v2.15.0 + +${MOCKERY_BIN}: ${UTILITY_BIN_PATH} + $(call go-get-tool,$(MOCKERY_BIN),github.com/vektra/mockery/v2@$(MOCKERY_VERSION)) + +mocks: ${MOCKERY_BIN} ## This target is used to generate all mocks for the dogu operator. + @cd $(WORKDIR)/controllers/internal && ${MOCKERY_BIN} --all + @echo "Mocks successfully created." \ No newline at end of file diff --git a/PROJECT b/PROJECT new file mode 100644 index 0000000..d3d2119 --- /dev/null +++ b/PROJECT @@ -0,0 +1,16 @@ +domain: cloudogu.com +layout: +- go.kubebuilder.io/v3 +projectName: k8s-backup-operator +repo: github.com/cloudogu/k8s-backup-operator +resources: +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: cloudogu.com + group: k8s + kind: Dogu + path: github.com/cloudogu/k8s-backup-operator/api/v1 + version: v1 +version: "3" diff --git a/README.md b/README.md index 8a3a823..d058dae 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# k8s-backup-operator \ No newline at end of file +# k8s-backup-operator +Cloudogu EcoSystem Dogu operator for Kubernetes + +--- + +### What is the Cloudogu EcoSystem? +The Cloudogu EcoSystem is an open platform, which lets you choose how and where your team creates great software. Each service or tool is delivered as a Dogu, a Docker container. Each Dogu can easily be integrated in your environment just by pulling it from our registry. We have a growing number of ready-to-use Dogus, e.g. SCM-Manager, Jenkins, Nexus, SonarQube, Redmine and many more. Every Dogu can be tailored to your specific needs. Take advantage of a central authentication service, a dynamic navigation, that lets you easily switch between the web UIs and a smart configuration magic, which automatically detects and responds to dependencies between Dogus. The Cloudogu EcoSystem is open source and it runs either on-premises or in the cloud. The Cloudogu EcoSystem is developed by Cloudogu GmbH under [MIT License](https://cloudogu.com/license.html). + +### How to get in touch? +Want to talk to the Cloudogu team? Need help or support? There are several ways to get in touch with us: + +* [Website](https://cloudogu.com) +* [myCloudogu-Forum](https://forum.cloudogu.com/topic/34?ctx=1) +* [Email hello@cloudogu.com](mailto:hello@cloudogu.com) + +--- +© 2023 Cloudogu GmbH - MADE WITH :heart: FOR DEV ADDICTS. [Legal notice / Impressum](https://cloudogu.com/imprint.html) diff --git a/build/.editorconfig b/build/.editorconfig new file mode 100644 index 0000000..f5f657b --- /dev/null +++ b/build/.editorconfig @@ -0,0 +1,2 @@ +[*.mk] +indent_style = tab diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..8197877 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,2 @@ +deb +tmp diff --git a/build/make/bats.mk b/build/make/bats.mk new file mode 100644 index 0000000..ce1319c --- /dev/null +++ b/build/make/bats.mk @@ -0,0 +1,64 @@ +WORKSPACE=/workspace +BATS_LIBRARY_DIR=$(TARGET_DIR)/bats_libs +TESTS_DIR=$(WORKDIR)/batsTests +BASH_TEST_REPORT_DIR=$(TARGET_DIR)/shell_test_reports +BASH_TEST_REPORTS=$(BASH_TEST_REPORT_DIR)/TestReport-*.xml +BATS_ASSERT=$(BATS_LIBRARY_DIR)/bats-assert +BATS_MOCK=$(BATS_LIBRARY_DIR)/bats-mock +BATS_SUPPORT=$(BATS_LIBRARY_DIR)/bats-support +BATS_FILE=$(BATS_LIBRARY_DIR)/bats-file +BATS_BASE_IMAGE?=bats/bats +BATS_CUSTOM_IMAGE?=cloudogu/bats +BATS_TAG?=1.2.1 +BATS_DIR=build/make/bats +BATS_WORKDIR="${WORKDIR}"/"${BATS_DIR}" + +.PHONY unit-test-shell: +unit-test-shell: unit-test-shell-$(ENVIRONMENT) + +$(BATS_ASSERT): + @git clone --depth 1 https://github.com/bats-core/bats-assert $@ + +$(BATS_MOCK): + @git clone --depth 1 https://github.com/grayhemp/bats-mock $@ + +$(BATS_SUPPORT): + @git clone --depth 1 https://github.com/bats-core/bats-support $@ + +$(BATS_FILE): + @git clone --depth 1 https://github.com/bats-core/bats-file $@ + +$(BASH_SRC): + BASH_SRC:=$(shell find "${WORKDIR}" -type f -name "*.sh") + +${BASH_TEST_REPORT_DIR}: $(TARGET_DIR) + @mkdir -p $(BASH_TEST_REPORT_DIR) + +unit-test-shell-ci: $(BASH_SRC) $(BASH_TEST_REPORT_DIR) $(BATS_ASSERT) $(BATS_MOCK) $(BATS_SUPPORT) $(BATS_FILE) + @echo "Test shell units on CI server" + @make unit-test-shell-generic + +unit-test-shell-local: $(BASH_SRC) $(PASSWD) $(ETCGROUP) $(HOME_DIR) buildTestImage $(BASH_TEST_REPORT_DIR) $(BATS_ASSERT) $(BATS_MOCK) $(BATS_SUPPORT) $(BATS_FILE) + @echo "Test shell units locally (in Docker)" + @docker run --rm \ + -v $(HOME_DIR):/home/$(USER) \ + -v $(WORKDIR):$(WORKSPACE) \ + -w $(WORKSPACE) \ + --entrypoint="" \ + $(BATS_CUSTOM_IMAGE):$(BATS_TAG) \ + "${BATS_DIR}"/customBatsEntrypoint.sh make unit-test-shell-generic-no-junit + +unit-test-shell-generic: + @bats --formatter junit --output ${BASH_TEST_REPORT_DIR} ${TESTS_DIR} + +unit-test-shell-generic-no-junit: + @bats ${TESTS_DIR} + +.PHONY buildTestImage: +buildTestImage: + @echo "Build shell test container" + @cd $(BATS_WORKDIR) && docker build \ + --build-arg=BATS_BASE_IMAGE=${BATS_BASE_IMAGE} \ + --build-arg=BATS_TAG=${BATS_TAG} \ + -t ${BATS_CUSTOM_IMAGE}:${BATS_TAG} \ + . \ No newline at end of file diff --git a/build/make/bats/Dockerfile b/build/make/bats/Dockerfile new file mode 100644 index 0000000..f75afe1 --- /dev/null +++ b/build/make/bats/Dockerfile @@ -0,0 +1,7 @@ +ARG BATS_BASE_IMAGE +ARG BATS_TAG + +FROM ${BATS_BASE_IMAGE}:${BATS_TAG} + +# Make bash more findable by scripts and tests +RUN apk add make git bash \ No newline at end of file diff --git a/build/make/bats/customBatsEntrypoint.sh b/build/make/bats/customBatsEntrypoint.sh new file mode 100755 index 0000000..58856fe --- /dev/null +++ b/build/make/bats/customBatsEntrypoint.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail + +"$@" \ No newline at end of file diff --git a/build/make/bower.mk b/build/make/bower.mk new file mode 100644 index 0000000..a2c76a9 --- /dev/null +++ b/build/make/bower.mk @@ -0,0 +1,28 @@ +##@ Bower dependency management + +BOWER_JSON=$(WORKDIR)/bower.json + +.PHONY: bower-install +bower-install: $(BOWER_TARGET) ## Execute yarn run bower (in Docker) + +ifeq ($(ENVIRONMENT), ci) + +$(BOWER_TARGET): $(BOWER_JSON) $(YARN_TARGET) + @echo "Yarn run bower on CI server" + @yarn run bower + +else + +$(BOWER_TARGET): $(BOWER_JSON) $(PASSWD) $(YARN_TARGET) + @echo "Executing bower..." + @docker run --rm \ + -e HOME=/tmp \ + -u "$(UID_NR):$(GID_NR)" \ + -v $(PASSWD):/etc/passwd:ro \ + -v $(WORKDIR):$(WORKDIR) \ + -w $(WORKDIR) \ + node:$(NODE_VERSION) \ + yarn run bower + @touch $@ + +endif diff --git a/build/make/build.mk b/build/make/build.mk new file mode 100644 index 0000000..b102149 --- /dev/null +++ b/build/make/build.mk @@ -0,0 +1,51 @@ +##@ Compiling go software + +ADDITIONAL_LDFLAGS?=-extldflags -static +LDFLAGS?=-ldflags "$(ADDITIONAL_LDFLAGS) -X main.Version=$(VERSION) -X main.CommitID=$(COMMIT_ID)" +GOIMAGE?=golang +GOTAG?=1.14.13 +GOOS?=linux +GOARCH?=amd64 +PRE_COMPILE?= +GO_ENV_VARS?= +CUSTOM_GO_MOUNT?=-v /tmp:/tmp +GO_BUILD_FLAGS?=-mod=vendor -a -tags netgo $(LDFLAGS) -installsuffix cgo -o $(BINARY) + +.PHONY: compile +compile: $(BINARY) ## Compile the go program via Docker + +compile-ci: ## Compile the go program without Docker + @echo "Compiling (CI)..." + make compile-generic + +compile-generic: + @echo "Compiling..." +# here is go called without mod capabilities because of error "go: error loading module requirements" +# see https://github.com/golang/go/issues/30868#issuecomment-474199640 + @$(GO_ENV_VARS) go build $(GO_BUILD_FLAGS) + + +ifeq ($(ENVIRONMENT), ci) + +$(BINARY): $(SRC) vendor $(PRE_COMPILE) + @echo "Built on CI server" + @make compile-generic + +else + +$(BINARY): $(SRC) vendor $(PASSWD) $(ETCGROUP) $(HOME_DIR) $(PRE_COMPILE) + @echo "Building locally (in Docker)" + @docker run --rm \ + -e GOOS=$(GOOS) \ + -e GOARCH=$(GOARCH) \ + -u "$(UID_NR):$(GID_NR)" \ + -v $(PASSWD):/etc/passwd:ro \ + -v $(ETCGROUP):/etc/group:ro \ + -v $(HOME_DIR):/home/$(USER) \ + -v $(WORKDIR):/go/src/github.com/cloudogu/$(ARTIFACT_ID) \ + $(CUSTOM_GO_MOUNT) \ + -w /go/src/github.com/cloudogu/$(ARTIFACT_ID) \ + $(GOIMAGE):$(GOTAG) \ + make compile-generic + +endif diff --git a/build/make/clean.mk b/build/make/clean.mk new file mode 100644 index 0000000..119387f --- /dev/null +++ b/build/make/clean.mk @@ -0,0 +1,15 @@ +##@ Cleaning + +.PHONY: clean +clean: $(ADDITIONAL_CLEAN) ## Remove target and tmp directories + rm -rf ${TARGET_DIR} + rm -rf ${TMP_DIR} + rm -rf ${UTILITY_BIN_PATH} + +.PHONY: dist-clean +dist-clean: clean ## Remove all generated directories + rm -rf node_modules + rm -rf public/vendor + rm -rf vendor + rm -rf npm-cache + rm -rf bower diff --git a/build/make/dependencies-gomod.mk b/build/make/dependencies-gomod.mk new file mode 100644 index 0000000..3b3b989 --- /dev/null +++ b/build/make/dependencies-gomod.mk @@ -0,0 +1,8 @@ +##@ Go mod dependency management + +.PHONY: dependencies +dependencies: vendor ## Install dependencies using go mod + +vendor: go.mod go.sum + @echo "Installing dependencies using go modules..." + ${GO_CALL} mod vendor diff --git a/build/make/deploy-debian.mk b/build/make/deploy-debian.mk new file mode 100644 index 0000000..89b0fbe --- /dev/null +++ b/build/make/deploy-debian.mk @@ -0,0 +1,65 @@ +##@ Debian package deployment + +# This Makefile holds all targets for deploying and undeploying +# Uses the variable APT_REPO to determine which apt repos should be used to deploy + +# Attention: This Makefile depends on package-debian.mk! + +.PHONY: deploy-check +deploy-check: + @case X"${VERSION}" in *-SNAPSHOT) echo "i will not upload a snaphot version for you" ; exit 1; esac; + @if [ X"${APT_API_USERNAME}" = X"" ] ; then echo "supply an APT_API_USERNAME environment variable"; exit 1; fi; + @if [ X"${APT_API_PASSWORD}" = X"" ] ; then echo "supply an APT_API_PASSWORD environment variable"; exit 1; fi; + @if [ X"${APT_API_SIGNPHRASE}" = X"" ] ; then echo "supply an APT_API_SIGNPHRASE environment variable"; exit 1; fi; + +.PHONY: upload-package +upload-package: deploy-check $(DEBIAN_PACKAGE) + @echo "... uploading package" + @$(APTLY) -F file=@"${DEBIAN_PACKAGE}" "${APT_API_BASE_URL}/files/$$(basename ${DEBIAN_PACKAGE})" + +.PHONY: add-package-to-repo +add-package-to-repo: upload-package +ifeq ($(APT_REPO), ces-premium) + @echo "... add package to ces-premium repository" + @$(APTLY) -X POST "${APT_API_BASE_URL}/repos/ces-premium/file/$$(basename ${DEBIAN_PACKAGE})" +else + @echo "\n... add package to ces repository" + @$(APTLY) -X POST "${APT_API_BASE_URL}/repos/ces/file/$$(basename ${DEBIAN_PACKAGE})" +endif + +define aptly_publish + $(APTLY) -X PUT -H "Content-Type: application/json" --data '{"Signing": { "Batch": true, "Passphrase": "${APT_API_SIGNPHRASE}"}}' ${APT_API_BASE_URL}/publish/$(1)/$(2) +endef + +.PHONY: publish +publish: + @echo "\n... publish packages" +ifeq ($(APT_REPO), ces-premium) + @$(call aptly_publish,ces-premium,bionic) +else + @$(call aptly_publish,ces,focal) + @$(call aptly_publish,ces,bionic) +endif + +.PHONY: deploy +deploy: add-package-to-repo publish ## Deploy package to apt repository + +define aptly_undeploy + PREF=$$(${APTLY} "${APT_API_BASE_URL}/repos/$(1)/packages?q=${ARTIFACT_ID}%20(${VERSION})"); \ + ${APTLY} -X DELETE -H 'Content-Type: application/json' --data "{\"PackageRefs\": $${PREF}}" ${APT_API_BASE_URL}/repos/$(1)/packages +endef + +.PHONY: remove-package-from-repo +remove-package-from-repo: +ifeq ($(APT_REPO), ces-premium) + @$(call aptly_undeploy,ces-premium) +else + @$(call aptly_undeploy,ces) +endif + +.PHONY: undeploy +undeploy: deploy-check remove-package-from-repo publish ## Undeploy package from apt repository + +.PHONE: lint-deb-package +lint-deb-package: debian ## Lint debian package + @lintian -i $(DEBIAN_PACKAGE) diff --git a/build/make/digital-signature.mk b/build/make/digital-signature.mk new file mode 100644 index 0000000..c0eba35 --- /dev/null +++ b/build/make/digital-signature.mk @@ -0,0 +1,24 @@ +##@ Digital signatures + +CHECKSUM=$(TARGET_DIR)/$(ARTIFACT_ID).sha256sum + +.PHONY: checksum +checksum: $(CHECKSUM) ## Generate checksums +# we have to depend on target dir, because we want to rebuild the checksum +# if one of the artefacts was changed +$(CHECKSUM): $(TARGET_DIR) + @echo "Generating Checksums" + @cd $(TARGET_DIR); find . -maxdepth 1 -not -type d | egrep -v ".(sha256sum|asc)$$" | xargs shasum -a 256 > $$(basename $@) + +SIGNATURE=$(CHECKSUM).asc + +.PHONY: signature +signature: $(SIGNATURE) ## Generate signature +$(SIGNATURE): $(CHECKSUM) + @echo "Generating Signature" + @gpg --batch --yes --detach-sign --armor -o $@ $< + +.PHONY: signature-ci +signature-ci: $(CHECKSUM) + @echo "Generating Signature" + @gpg2 --batch --pinentry-mode loopback --passphrase="${passphrase}" --yes --detach-sign --armor -o ${SIGNATURE} $< diff --git a/build/make/k8s-controller.mk b/build/make/k8s-controller.mk new file mode 100644 index 0000000..feadb0c --- /dev/null +++ b/build/make/k8s-controller.mk @@ -0,0 +1,96 @@ +# This script can be used to build and deploy kubernetes controllers. It is required to implement the controller +# specific targets `manifests` and `generate`: +# +# Examples: +# +#.PHONY: manifests +#manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. +# @echo "Generate manifests..." +# @$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases +# +#.PHONY: generate +#generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. +# @echo "Auto-generate deepcopy functions..." +# @$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." + +# This script requires the k8s.mk script +include $(WORKDIR)/build/make/k8s.mk + +## Variables + +# Setting SHELL to bash allows bash commands to be executed by recipes. +# This is a requirement for 'setup-envtest.sh' in the test target. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec + +# make sure to create a statically linked binary otherwise it may quit with +# "exec user process caused: no such file or directory" +GO_BUILD_FLAGS=-mod=vendor -a -tags netgo,osusergo $(LDFLAGS) -o $(BINARY) + +# remove DWARF symbol table and strip other symbols to shave ~13 MB from binary +ADDITIONAL_LDFLAGS=-extldflags -static -w -s + +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. +ENVTEST_K8S_VERSION = 1.23 +K8S_INTEGRATION_TEST_DIR=${TARGET_DIR}/k8s-integration-test + +##@ K8s - EcoSystem + +.PHONY: build +build: image-import k8s-apply ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. + +##@ Release + +.PHONY: controller-release +controller-release: ## Interactively starts the release workflow. + @echo "Starting git flow release..." + @build/make/release.sh controller-tool + +##@ K8s - Development + +.PHONY: build-controller +build-controller: ${SRC} compile ## Builds the controller Go binary. + +# Allows to perform tasks before locally running the controller +K8S_RUN_PRE_TARGETS ?= +.PHONY: run +run: manifests generate $(K8S_RUN_PRE_TARGETS) ## Run a controller from your host. + go run -ldflags "-X main.Version=$(VERSION)" ./main.go + +##@ K8s - Integration test with envtest + +$(K8S_INTEGRATION_TEST_DIR): + @mkdir -p $@ + +.PHONY: k8s-integration-test +k8s-integration-test: $(K8S_INTEGRATION_TEST_DIR) manifests generate envtest ## Run k8s integration tests. + @echo "Running K8s integration tests..." + @KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -tags=k8s_integration ./... -coverprofile ${K8S_INTEGRATION_TEST_DIR}/report-k8s-integration.out + +##@ K8s - Controller Resource + +# The pre generation script creates a K8s resource yaml containing generated manager yaml. +.PHONY: k8s-create-temporary-resource + k8s-create-temporary-resource: $(K8S_RESOURCE_TEMP_FOLDER) manifests kustomize + @echo "Generating temporary k8s resources $(K8S_RESOURCE_TEMP_YAML)..." + cd $(WORKDIR)/config/manager && $(KUSTOMIZE) edit set image controller=$(IMAGE) + $(KUSTOMIZE) build config/default > $(K8S_RESOURCE_TEMP_YAML) + @echo "Done." + +##@ K8s - Download Kubernetes Utility Tools + +CONTROLLER_GEN = $(UTILITY_BIN_PATH)/controller-gen +.PHONY: controller-gen +controller-gen: ## Download controller-gen locally if necessary. + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0) + +KUSTOMIZE = $(UTILITY_BIN_PATH)/kustomize +.PHONY: kustomize +kustomize: ## Download kustomize locally if necessary. + $(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.2) + +ENVTEST = $(UTILITY_BIN_PATH)/setup-envtest +.PHONY: envtest +envtest: ## Download envtest-setup locally if necessary. + $(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) \ No newline at end of file diff --git a/build/make/k8s-dogu.mk b/build/make/k8s-dogu.mk new file mode 100644 index 0000000..17a39d9 --- /dev/null +++ b/build/make/k8s-dogu.mk @@ -0,0 +1,44 @@ +# Variables +# Path to the dogu json of the dogu +DOGU_JSON_FILE=$(WORKDIR)/dogu.json +DOGU_JSON_DEV_FILE=${TARGET_DIR}/dogu.json +# Name of the dogu is extracted from the dogu.json +ARTIFACT_ID=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|.*/||g") +# Namespace of the dogu is extracted from the dogu.json +ARTIFACT_NAMESPACE=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|/.*||g") +# Namespace of the dogu is extracted from the dogu.json +VERSION=$(shell $(BINARY_YQ) -e ".Version" $(DOGU_JSON_FILE)) +# Image of the dogu is extracted from the dogu.json +IMAGE=$(shell $(BINARY_YQ) -e ".Image" $(DOGU_JSON_FILE)):$(VERSION) +IMAGE_DEV_WITHOUT_TAG=$(shell $(BINARY_YQ) -e ".Image" $(DOGU_JSON_FILE) | sed "s|registry\.cloudogu\.com\(.\+\)|${K3CES_REGISTRY_URL_PREFIX}\1|g") +IMAGE_DEV=${IMAGE_DEV_WITHOUT_TAG}:${VERSION} + +include $(WORKDIR)/build/make/k8s.mk + +##@ K8s - EcoSystem + +.PHONY: build +build: image-import install-dogu-descriptor k8s-apply ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. + +##@ K8s - Dogu - Resource + +# The additional k8s yaml files +K8S_RESOURCE_PRODUCTIVE_FOLDER ?= $(WORKDIR)/k8s +K8S_RESOURCE_PRODUCTIVE_YAML ?= $(K8S_RESOURCE_PRODUCTIVE_FOLDER)/$(ARTIFACT_ID).yaml +K8S_RESOURCE_DOGU_CR_TEMPLATE_YAML ?= $(WORKDIR)/build/make/k8s-dogu.tpl +# The pre generation script creates a k8s resource yaml containing the dogu crd and the content from the k8s folder. +.PHONY: k8s-create-temporary-resource + k8s-create-temporary-resource: ${BINARY_YQ} $(K8S_RESOURCE_TEMP_FOLDER) + @echo "Generating temporary K8s resources $(K8S_RESOURCE_TEMP_YAML)..." + @rm -f $(K8S_RESOURCE_TEMP_YAML) + @sed "s|NAMESPACE|$(ARTIFACT_NAMESPACE)|g" $(K8S_RESOURCE_DOGU_CR_TEMPLATE_YAML) | sed "s|NAME|$(ARTIFACT_ID)|g" | sed "s|VERSION|$(VERSION)|g" >> $(K8S_RESOURCE_TEMP_YAML) + @echo "Done." + +##@ K8s - Dogu + +.PHONY: install-dogu-descriptor +install-dogu-descriptor: ${BINARY_YQ} $(TARGET_DIR) ## Installs a configmap with current dogu.json into the cluster. + @echo "Generate configmap from dogu.json..." + @$(BINARY_YQ) ".Image=\"${IMAGE_DEV_WITHOUT_TAG}\"" ${DOGU_JSON_FILE} > ${DOGU_JSON_DEV_FILE} + @kubectl create configmap "$(ARTIFACT_ID)-descriptor" --from-file=$(DOGU_JSON_DEV_FILE) --dry-run=client -o yaml | kubectl apply -f - + @echo "Done." diff --git a/build/make/k8s-dogu.tpl b/build/make/k8s-dogu.tpl new file mode 100644 index 0000000..44cd9cf --- /dev/null +++ b/build/make/k8s-dogu.tpl @@ -0,0 +1,9 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: NAME + labels: + dogu: NAME +spec: + name: NAMESPACE/NAME + version: VERSION \ No newline at end of file diff --git a/build/make/k8s.mk b/build/make/k8s.mk new file mode 100644 index 0000000..a9233d0 --- /dev/null +++ b/build/make/k8s.mk @@ -0,0 +1,124 @@ +# This file is optional and can be used to set personal information without committing them to the repository. +MY_ENV_FILE ?= $(WORKDIR)/.env +ifneq (,$(wildcard $(MY_ENV_FILE))) + include .env +endif + +## Variables + +BINARY_YQ = $(UTILITY_BIN_PATH)/yq + +# The cluster root variable is used to the build images to the cluster. It can be defined in a .myenv file. +K8S_CLUSTER_ROOT ?= +# The productive tag of the image +IMAGE ?= + +K3S_CLUSTER_FQDN?=k3ces.local +K3S_LOCAL_REGISTRY_PORT?=30099 +K3CES_REGISTRY_URL_PREFIX="${K3S_CLUSTER_FQDN}:${K3S_LOCAL_REGISTRY_PORT}" + +# Variables for the temporary yaml files. These are used as template to generate a development resource containing +# the current namespace and the dev image. +K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR)/make/k8s +K8S_RESOURCE_TEMP_YAML ?= $(K8S_RESOURCE_TEMP_FOLDER)/$(ARTIFACT_ID)_$(VERSION).yaml + +# The current namespace is extracted from the current context. +K8S_CURRENT_NAMESPACE=$(shell kubectl config view --minify -o jsonpath='{..namespace}') + +##@ K8s - Variables + +.PHONY: check-all-vars +check-all-vars: check-k8s-cluster-root-env-var check-k8s-image-env-var check-k8s-artifact-id check-etc-hosts check-insecure-cluster-registry ## Conduct a sanity check against selected build artefacts or local environment + +.PHONY: check-k8s-cluster-root-env-var +check-k8s-cluster-root-env-var: + @$(call check_defined, K8S_CLUSTER_ROOT, root path of your k3ces) + +.PHONY: check-k8s-image-env-var +check-k8s-image-env-var: + @$(call check_defined, IMAGE, docker image tag) + +.PHONY: check-k8s-artifact-id +check-k8s-artifact-id: + @$(call check_defined, ARTIFACT_ID, app/dogu name) + +.PHONY: check-etc-hosts +check-etc-hosts: + @grep -E "^.+\s+${K3S_CLUSTER_FQDN}\$$" /etc/hosts > /dev/null || \ + (echo "Missing /etc/hosts entry for ${K3S_CLUSTER_FQDN}" && exit 1) + +.PHONY: check-insecure-cluster-registry +check-insecure-cluster-registry: + @grep "${K3CES_REGISTRY_URL_PREFIX}" /etc/docker/daemon.json > /dev/null || \ + (echo "Missing /etc/docker/daemon.json for ${K3CES_REGISTRY_URL_PREFIX}" && exit 1) + +##@ K8s - Resources + +${K8S_RESOURCE_TEMP_FOLDER}: + @mkdir -p $@ + +.PHONY: k8s-delete +k8s-delete: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Deletes all dogu related resources from the K8s cluster. + @echo "Delete old dogu resources..." + @kubectl delete -f $(K8S_RESOURCE_TEMP_YAML) --wait=false --ignore-not-found=true + +# The additional targets executed after the generate target, executed before each apply and delete. The generate target +# produces a temporary yaml. This yaml is accessible via K8S_RESOURCE_TEMP_YAML an can be changed before the apply/delete. +K8S_POST_GENERATE_TARGETS ?= +# The additional targets executed before the generate target, executed before each apply and delete. +K8S_PRE_GENERATE_TARGETS ?= k8s-create-temporary-resource + +.PHONY: k8s-generate +k8s-generate: ${BINARY_YQ} $(K8S_RESOURCE_TEMP_FOLDER) $(K8S_PRE_GENERATE_TARGETS) ## Generates the final resource yaml. + @echo "Applying general transformations..." + @sed -i "s/'{{ .Namespace }}'/$(K8S_CURRENT_NAMESPACE)/" $(K8S_RESOURCE_TEMP_YAML) + @$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").image)=\"$(IMAGE_DEV)\"" $(K8S_RESOURCE_TEMP_YAML) + @echo "Done." + +.PHONY: k8s-apply +k8s-apply: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Applies all generated K8s resources to the current cluster and namespace. + @echo "Apply generated K8s resources..." + @kubectl apply -f $(K8S_RESOURCE_TEMP_YAML) + +##@ K8s - Docker + +.PHONY: docker-build +docker-build: check-k8s-image-env-var ## Builds the docker image of the K8s app. + @echo "Building docker image..." + DOCKER_BUILDKIT=1 docker build . -t $(IMAGE) + +.PHONY: docker-dev-tag +docker-dev-tag: check-k8s-image-dev-var docker-build ## Tags a Docker image for local K3ces deployment. + @echo "Tagging image with dev tag..." + DOCKER_BUILDKIT=1 docker tag ${IMAGE} ${IMAGE_DEV} + +.PHONY: check-k8s-image-dev-var +check-k8s-image-dev-var: +ifeq (${IMAGE_DEV},) + @echo "Missing make variable IMAGE_DEV detected. It should look like \$${K3CES_REGISTRY_URL_PREFIX}/docker-image:tag" + @exit 19 +endif + +.PHONY: image-import +image-import: check-all-vars check-k8s-artifact-id docker-dev-tag ## Imports the currently available image into the cluster-local registry. + @echo "Import ${IMAGE_DEV} into K8s cluster ${K3S_CLUSTER_FQDN}..." + @docker push ${IMAGE_DEV} + @echo "Done." + +## Functions + +# Check that given variables are set and all have non-empty values, +# die with an error otherwise. +# +# Params: +# 1. Variable name(s) to test. +# 2. (optional) Error message to print. +check_defined = \ + $(strip $(foreach 1,$1, \ + $(call __check_defined,$1,$(strip $(value 2))))) +__check_defined = \ + $(if $(value $1),, \ + $(error Undefined $1$(if $2, ($2)))) + +${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download controller-gen locally if necessary. + $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) \ No newline at end of file diff --git a/build/make/package-debian.mk b/build/make/package-debian.mk new file mode 100644 index 0000000..ad55ea1 --- /dev/null +++ b/build/make/package-debian.mk @@ -0,0 +1,79 @@ +##@ Debian packaging + +# This Makefile holds all targets for building a debian package +# For deployment of the deb package include the deploy-debian.mk! + +PREPARE_PACKAGE?=prepare-package +DEBIAN_PACKAGE_FORMAT_VERSION="2.0" +CONFFILES_FILE="$(DEBIAN_CONTENT_DIR)/control/conffiles" +CONFFILES_FILE_TMP="$(DEBIAN_CONTENT_DIR)/conffiles_" +DEBSRC:=$(shell find "${WORKDIR}/deb" -type f) + +.PHONY: package +package: debian-with-binary ## Build binary and package into .deb file + +.PHONY: debian +debian: $(DEBIAN_PACKAGE) ## Create .deb package without building the binary before + +.PHONY: debian-with-binary +debian-with-binary: $(BINARY) $(DEBIAN_PACKAGE) + +.PHONY: prepare-package +prepare-package: + @echo "Using default prepare-package target. To write your own, define a target and specify it in the PREPARE_PACKAGE variable, before the package-debian.mk import" + +$(DEBIAN_BUILD_DIR): + @mkdir $@ + +$(DEBIAN_BUILD_DIR)/debian-binary: $(DEBIAN_BUILD_DIR) + @echo $(DEBIAN_PACKAGE_FORMAT_VERSION) > $@ + +$(DEBIAN_CONTENT_DIR)/control: + @install -p -m 0755 -d $@ + +$(DEBIAN_CONTENT_DIR)/data: + @install -p -m 0755 -d $@ + +$(DEBIAN_PACKAGE): $(TARGET_DIR) $(DEBIAN_CONTENT_DIR)/control $(DEBIAN_CONTENT_DIR)/data $(DEBIAN_BUILD_DIR)/debian-binary $(PREPARE_PACKAGE) $(DEBSRC) + @echo "Creating .deb package..." + +# populate control directory + @sed -e "s/^Version:.*/Version: $(VERSION)/g" deb/DEBIAN/control > $(DEBIAN_CONTENT_DIR)/_control + @install -p -m 0644 $(DEBIAN_CONTENT_DIR)/_control $(DEBIAN_CONTENT_DIR)/control/control + +# populate data directory + @for dir in $$(find deb -mindepth 1 -not -name "DEBIAN" -a -type d |sed s@"^deb/"@"$(DEBIAN_CONTENT_DIR)/data/"@) ; do \ + install -m 0755 -d $${dir} ; \ + done + + @for file in $$(find deb -mindepth 1 -type f | grep -v "DEBIAN") ; do \ + cp $${file} $(DEBIAN_CONTENT_DIR)/data/$${file#deb/} ; \ + done + +# Copy binary to data/usr/sbin, if it exists + @if [ -f $(BINARY) ]; then \ + echo "Copying binary to $(DEBIAN_CONTENT_DIR)/data/usr/sbin"; \ + install -p -m 0755 -d $(DEBIAN_CONTENT_DIR)/data/usr/sbin; \ + install -p -m 0755 $(BINARY) $(DEBIAN_CONTENT_DIR)/data/usr/sbin/; \ + fi + +# create conffiles file which help to deal with config change +# in order to successfully add the conffiles file to the archive it must exist, even empty + @touch $(CONFFILES_FILE_TMP) + @for file in $$(find $(DEBIAN_CONTENT_DIR)/data/etc -mindepth 1 -type f | grep -v "DEBIAN") ; do \ + echo $$file | sed s@'.*\(/etc/\)@\1'@ >> $(CONFFILES_FILE_TMP) ; \ + done + @install -p -m 0644 $(CONFFILES_FILE_TMP) $(CONFFILES_FILE) + @rm $(CONFFILES_FILE_TMP) + +# create control.tar.gz + @tar cvfz $(DEBIAN_CONTENT_DIR)/control.tar.gz -C $(DEBIAN_CONTENT_DIR)/control $(TAR_ARGS) . + +# create data.tar.gz + @tar cvfz $(DEBIAN_CONTENT_DIR)/data.tar.gz -C $(DEBIAN_CONTENT_DIR)/data $(TAR_ARGS) . + +# create package + @ar roc $@ $(DEBIAN_BUILD_DIR)/debian-binary $(DEBIAN_CONTENT_DIR)/control.tar.gz $(DEBIAN_CONTENT_DIR)/data.tar.gz + @echo "... deb package can be found at $@" + +APTLY:=curl --silent --show-error --fail -u "${APT_API_USERNAME}":"${APT_API_PASSWORD}" diff --git a/build/make/package-tar.mk b/build/make/package-tar.mk new file mode 100644 index 0000000..9b842a3 --- /dev/null +++ b/build/make/package-tar.mk @@ -0,0 +1,10 @@ +##@ Tar packaging + +TAR_PACKAGE:=$(ARTIFACT_ID)-$(VERSION).tar.gz + +.PHONY: package +package: $(TAR_PACKAGE) ## Build binary and create tar package from it + +$(TAR_PACKAGE): $(BINARY) + # Check owner and group id + tar cvfz $(TARGET_DIR)/$(TAR_PACKAGE) -C $(TARGET_DIR) $$(basename ${BINARY}) $(TAR_ARGS) diff --git a/build/make/release.mk b/build/make/release.mk new file mode 100644 index 0000000..11dde9a --- /dev/null +++ b/build/make/release.mk @@ -0,0 +1,11 @@ +##@ Releases + +# This makefile holds the dogu-release target for starting a new dogu release + +.PHONY: dogu-release +dogu-release: ## Start a dogu release + build/make/release.sh dogu + +.PHONY: go-release +go-release: ## Start a go tool release + build/make/release.sh go-tool \ No newline at end of file diff --git a/build/make/release.sh b/build/make/release.sh new file mode 100755 index 0000000..4fd4569 --- /dev/null +++ b/build/make/release.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail + +# Extension points in release.sh: +# +# A custom release argument file will be sourced if found. The custom release arg file may implement one or more bash +# functions which either release.sh or release_functions.sh define. If such a custom release function is found the +# release script must define the argument list which the custom release function will receive during the release. + +sourceCustomReleaseArgs() { + RELEASE_ARGS_FILE="${1}" + + if [[ -f "${RELEASE_ARGS_FILE}" ]]; then + echo "Using custom release args file ${RELEASE_ARGS_FILE}" + + sourceCustomReleaseExitCode=0 + # shellcheck disable=SC1090 + source "${RELEASE_ARGS_FILE}" || sourceCustomReleaseExitCode=$? + if [[ ${sourceCustomReleaseExitCode} -ne 0 ]]; then + echo "Error while sourcing custom release arg file ${sourceCustomReleaseExitCode}. Exiting." + exit 9 + fi + fi +} + +PROJECT_DIR="$(pwd)" +RELEASE_ARGS_FILE="${PROJECT_DIR}/release_args.sh" + +sourceCustomReleaseArgs "${RELEASE_ARGS_FILE}" + +source "$(pwd)/build/make/release_functions.sh" + +TYPE="${1}" + +echo "=====Starting Release process=====" + +if [ "${TYPE}" == "dogu" ];then + CURRENT_TOOL_VERSION=$(get_current_version_by_dogu_json) +else + CURRENT_TOOL_VERSION=$(get_current_version_by_makefile) +fi + +NEW_RELEASE_VERSION="$(read_new_version)" + +validate_new_version "${NEW_RELEASE_VERSION}" +start_git_flow_release "${NEW_RELEASE_VERSION}" +update_versions "${NEW_RELEASE_VERSION}" +update_changelog "${NEW_RELEASE_VERSION}" +show_diff +finish_release_and_push "${CURRENT_TOOL_VERSION}" "${NEW_RELEASE_VERSION}" + +echo "=====Finished Release process=====" diff --git a/build/make/release_functions.sh b/build/make/release_functions.sh new file mode 100755 index 0000000..528806b --- /dev/null +++ b/build/make/release_functions.sh @@ -0,0 +1,220 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail + +wait_for_ok(){ + printf "\n" + OK=false + while [[ ${OK} != "ok" ]] ; do + read -r -p "${1} (type 'ok'): " OK + done +} + +ask_yes_or_no(){ + local ANSWER="" + + while [ "${ANSWER}" != "y" ] && [ "${ANSWER}" != "n" ]; do + read -r -p "${1} (type 'y/n'): " ANSWER + done + + echo "${ANSWER}" +} + +get_current_version_by_makefile(){ + grep '^VERSION=[0-9[:alpha:].-]*$' Makefile | sed s/VERSION=//g +} + +get_current_version_by_dogu_json(){ + jq ".Version" --raw-output dogu.json +} + +read_new_version(){ + local NEW_RELEASE_VERSION + read -r -p "Current Version is v${CURRENT_TOOL_VERSION}. Please provide the new version: v" NEW_RELEASE_VERSION + echo "${NEW_RELEASE_VERSION}" +} + +validate_new_version(){ + local NEW_RELEASE_VERSION="${1}" + # Validate that release version does not start with vv + if [[ ${NEW_RELEASE_VERSION} = v* ]]; then + echo "WARNING: The new release version (v${NEW_RELEASE_VERSION}) starts with 'vv'." + echo "You must not enter the v when defining the new version." + ANSWER=$(ask_yes_or_no "Should the first v be removed?") + if [ "${ANSWER}" == "y" ]; then + NEW_RELEASE_VERSION="${NEW_RELEASE_VERSION:1}" + echo "Release version now is: ${NEW_RELEASE_VERSION}" + fi + fi; +} + +start_git_flow_release(){ + local NEW_RELEASE_VERSION="${1}" + # Do gitflow + git flow init --defaults --force + + mainBranchExists="$(git show-ref refs/remotes/origin/main || echo "")" + if [ -n "$mainBranchExists" ]; then + echo 'Using "main" branch for production releases' + git flow config set master main + git checkout main + git pull origin main + else + echo 'Using "master" branch for production releases' + git checkout master + git pull origin master + fi + + git checkout develop + git pull origin develop + git flow release start v"${NEW_RELEASE_VERSION}" +} + +# update_versions updates files with the new release version and interactively asks the user for verification. If okay +# the updated files will be staged to git and finally committed. +# +# extension points: +# - update_versions_modify_files - update a file with the new version number +# - update_versions_stage_modified_files - stage a modified file to prepare the file for the up-coming commit +update_versions(){ + local NEW_RELEASE_VERSION="${1}" + + if [[ $(type -t update_versions_modify_files) == function ]]; then + preSkriptExitCode=0 + update_versions_modify_files "${NEW_RELEASE_VERSION}" || preSkriptExitCode=$? + if [[ ${preSkriptExitCode} -ne 0 ]]; then + echo "ERROR: custom update_versions_modify_files() exited with exit code ${preSkriptExitCode}" + exit 1 + fi + fi + + # Update version in dogu.json + if [ -f "dogu.json" ]; then + echo "Updating version in dogu.json..." + jq ".Version = \"${NEW_RELEASE_VERSION}\"" dogu.json > dogu2.json && mv dogu2.json dogu.json + fi + + # Update version in Dockerfile + if [ -f "Dockerfile" ]; then + echo "Updating version in Dockerfile..." + sed -i "s/\(^[ ]*VERSION=\"\)\([^\"]*\)\(.*$\)/\1${NEW_RELEASE_VERSION}\3/" Dockerfile + fi + + # Update version in Makefile + if [ -f "Makefile" ]; then + echo "Updating version in Makefile..." + sed -i "s/\(^VERSION=\)\(.*\)$/\1${NEW_RELEASE_VERSION}/" Makefile + fi + + # Update version in package.json + if [ -f "package.json" ]; then + echo "Updating version in package.json..." + jq ".version = \"${NEW_RELEASE_VERSION}\"" package.json > package2.json && mv package2.json package.json + fi + + # Update version in pom.xml + if [ -f "pom.xml" ]; then + echo "Updating version in pom.xml..." + mvn versions:set -DgenerateBackupPoms=false -DnewVersion="${NEW_RELEASE_VERSION}" + fi + + wait_for_ok "Please make sure that all versions have been updated correctly now (e.g. via \"git diff\")." + + ### The `git add` command has to be after the okay. Otherwise user-made changes to versions would not be added. + + if [[ $(type -t update_versions_stage_modified_files) == function ]]; then + preSkriptExitCode=0 + update_versions_stage_modified_files "${NEW_RELEASE_VERSION}" || preSkriptExitCode=$? + if [[ ${preSkriptExitCode} -ne 0 ]]; then + echo "ERROR: custom update_versions_stage_modified_files exited with exit code ${preSkriptExitCode}" + exit 1 + fi + fi + + if [ -f "dogu.json" ]; then + git add dogu.json + fi + + if [ -f "Dockerfile" ]; then + git add Dockerfile + fi + + if [ -f "Makefile" ]; then + git add Makefile + fi + + if [ -f "package.json" ]; then + git add package.json + fi + + if [ -f "pom.xml" ]; then + git add pom.xml + fi + + git commit -m "Bump version" +} + +update_changelog(){ + local NEW_RELEASE_VERSION="${1}" + + # Changelog update + CURRENT_DATE=$(date --rfc-3339=date) + NEW_CHANGELOG_TITLE="## [v${NEW_RELEASE_VERSION}] - ${CURRENT_DATE}" + # Check if "Unreleased" tag exists + while ! grep --silent "## \[Unreleased\]" CHANGELOG.md; do + echo "" + echo -e "\e[31mYour CHANGELOG.md does not contain a \"## [Unreleased]\" line!\e[0m" + echo "Please add one to make it comply to https://keepachangelog.com/en/1.0.0/" + wait_for_ok "Please insert a \"## [Unreleased]\" line into CHANGELOG.md now." + done + + # Add new title line to changelog + sed -i "s|## \[Unreleased\]|## \[Unreleased\]\n\n${NEW_CHANGELOG_TITLE}|g" CHANGELOG.md + + # Wait for user to validate changelog changes + wait_for_ok "Please make sure your CHANGELOG.md looks as desired." + + # Check if new version tag still exists + while ! grep --silent "## \[v${NEW_RELEASE_VERSION}\] - ${CURRENT_DATE}" CHANGELOG.md; do + echo "" + echo -e "\e[31mYour CHANGELOG.md does not contain \"${NEW_CHANGELOG_TITLE}\"!\e[0m" + wait_for_ok "Please update your CHANGELOG.md now." + done + + git add CHANGELOG.md + git commit -m "Update changelog" +} + +show_diff(){ + if ! git diff --exit-code > /dev/null; then + echo "There are still uncommitted changes:" + echo "" + echo "# # # # # # # # # #" + echo "" + git --no-pager diff + echo "" + echo "# # # # # # # # # #" + fi + + echo "All changes compared to develop branch:" + echo "" + echo "# # # # # # # # # #" + echo "" + git --no-pager diff develop + echo "" + echo "# # # # # # # # # #" +} + +finish_release_and_push(){ + local CURRENT_VERSION="${1}" + local NEW_RELEASE_VERSION="${2}" + + # Push changes and delete release branch + wait_for_ok "Upgrade from version v${CURRENT_VERSION} to version v${NEW_RELEASE_VERSION} finished. Should the changes be pushed?" + git push origin release/v"${NEW_RELEASE_VERSION}" + + echo "Switching back to develop and deleting branch release/v${NEW_RELEASE_VERSION}..." + git checkout develop + git branch -D release/v"${NEW_RELEASE_VERSION}" +} diff --git a/build/make/self-update.mk b/build/make/self-update.mk new file mode 100644 index 0000000..175f8a6 --- /dev/null +++ b/build/make/self-update.mk @@ -0,0 +1,22 @@ +##@ Makefile management + +.PHONY: update-makefiles +update-makefiles: do-update-makefiles ## Update Makefiles to MAKEFILES_VERSION + +.PHONY: do-update-makefiles +do-update-makefiles: $(TMP_DIR) download-and-extract remove-old-files copy-new-files + @echo Updating makefiles... + +.PHONY: download-and-extract +download-and-extract: + @curl -L --silent https://github.com/cloudogu/makefiles/archive/v$(MAKEFILES_VERSION).tar.gz > $(TMP_DIR)/makefiles-v$(MAKEFILES_VERSION).tar.gz + @tar -xzf $(TMP_DIR)/makefiles-v$(MAKEFILES_VERSION).tar.gz -C $(TMP_DIR) + +.PHONY: remove-old-files +remove-old-files: + @echo "Deleting old files" + rm -rf $(BUILD_DIR)/make + +.PHONY: copy-new-files +copy-new-files: + @cp -r $(TMP_DIR)/makefiles-$(MAKEFILES_VERSION)/build/make $(BUILD_DIR) \ No newline at end of file diff --git a/build/make/static-analysis.mk b/build/make/static-analysis.mk new file mode 100644 index 0000000..70e6468 --- /dev/null +++ b/build/make/static-analysis.mk @@ -0,0 +1,66 @@ +##@ Static analysis + +STATIC_ANALYSIS_DIR=$(TARGET_DIR)/static-analysis +GOIMAGE?=golang +GOTAG?=1.18 +CUSTOM_GO_MOUNT?=-v /tmp:/tmp + +REVIEW_DOG=$(TMP_DIR)/bin/reviewdog +LINT=$(TMP_DIR)/bin/golangci-lint +LINT_VERSION?=v1.49.0 +# ignore tests and mocks +LINTFLAGS=--tests=false --skip-files="^.*_mock.go$$" --skip-files="^.*/mock.*.go$$" --timeout 10m --issues-exit-code 0 +ADDITIONAL_LINTER=-E bodyclose -E containedctx -E contextcheck -E decorder -E dupl -E errname -E forcetypeassert -E funlen -E unparam + +.PHONY: static-analysis +static-analysis: static-analysis-$(ENVIRONMENT) ## Start a static analysis of the code + +.PHONY: static-analysis-ci +static-analysis-ci: + @make $(STATIC_ANALYSIS_DIR)/static-analysis-cs.log $(STATIC_ANALYSIS_DIR)/static-analysis.log static-analysis-ci-report-pr + +static-analysis-ci-report-pr: $(REVIEW_DOG) + @if [ X"$(CI_PULL_REQUEST)" != X"" -a X"$(CI_PULL_REQUEST)" != X"null" ] ; then \ + cat $(STATIC_ANALYSIS_DIR)/static-analysis-cs.log | CI_COMMIT=$(COMMIT_ID) $(REVIEW_DOG) -f=checkstyle -reporter="github-pr-review"; \ + fi + +.PHONY: static-analysis-local +static-analysis-local: $(PASSWD) $(ETCGROUP) $(HOME_DIR) + @docker run --rm \ + -e GOOS=$(GOOS) \ + -e GOARCH=$(GOARCH) \ + -u "$(UID_NR):$(GID_NR)" \ + -v $(PASSWD):/etc/passwd:ro \ + -v $(ETCGROUP):/etc/group:ro \ + -v $(HOME_DIR):/home/$(USER) \ + -v $(WORKDIR):/go/src/github.com/cloudogu/$(ARTIFACT_ID) \ + $(CUSTOM_GO_MOUNT) \ + -w /go/src/github.com/cloudogu/$(ARTIFACT_ID) \ + $(GOIMAGE):$(GOTAG) \ + make $(STATIC_ANALYSIS_DIR)/static-analysis-cs.log $(STATIC_ANALYSIS_DIR)/static-analysis.log static-analysis-ci-report-local + +$(STATIC_ANALYSIS_DIR)/static-analysis.log: $(STATIC_ANALYSIS_DIR) + @echo "" + @echo "complete static analysis:" + @echo "" + @$(LINT) $(LINTFLAGS) run ./... $(ADDITIONAL_LINTER) > $@ + +$(STATIC_ANALYSIS_DIR)/static-analysis-cs.log: $(STATIC_ANALYSIS_DIR) + @echo "run static analysis with export to checkstyle format" + @$(LINT) $(LINTFLAGS) run --out-format=checkstyle ./... $(ADDITIONAL_LINTER) > $@ + +$(STATIC_ANALYSIS_DIR): $(LINT) + @mkdir -p $(STATIC_ANALYSIS_DIR) + +static-analysis-ci-report-local: $(STATIC_ANALYSIS_DIR)/static-analysis-cs.log $(REVIEW_DOG) + @echo "" + @echo "differences to develop branch:" + @echo "" + @cat $(STATIC_ANALYSIS_DIR)/static-analysis-cs.log | $(REVIEW_DOG) -f checkstyle -diff "git diff develop" + +$(LINT): $(TMP_DIR) + @echo "Download golangci-lint $(LINT_VERSION)..." + @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TMP_DIR)/bin $(LINT_VERSION) + +$(REVIEW_DOG): $(TMP_DIR) + @curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh| sh -s -- -b $(TMP_DIR)/bin diff --git a/build/make/test-common.mk b/build/make/test-common.mk new file mode 100644 index 0000000..6eaa0da --- /dev/null +++ b/build/make/test-common.mk @@ -0,0 +1,6 @@ +GO_JUNIT_REPORT=$(UTILITY_BIN_PATH)/go-junit-report +GO_JUNIT_REPORT_VERSION=v1.0.0 + +$(GO_JUNIT_REPORT): $(UTILITY_BIN_PATH) + @echo "Download go-junit-report..." + @$(call go-get-tool,$@,github.com/jstemmer/go-junit-report@$(GO_JUNIT_REPORT_VERSION)) diff --git a/build/make/test-integration.mk b/build/make/test-integration.mk new file mode 100644 index 0000000..9a3103c --- /dev/null +++ b/build/make/test-integration.mk @@ -0,0 +1,49 @@ +##@ Integration testing + +INTEGRATION_TEST_DIR=$(TARGET_DIR)/integration-tests +XUNIT_INTEGRATION_XML=$(INTEGRATION_TEST_DIR)/integration-tests.xml +INTEGRATION_TEST_LOG=$(INTEGRATION_TEST_DIR)/integration-tests.log +INTEGRATION_TEST_REPORT=$(INTEGRATION_TEST_DIR)/coverage.out +PRE_INTEGRATIONTESTS?=start-local-docker-compose +POST_INTEGRATIONTESTS?=stop-local-docker-compose +INTEGRATION_TEST_NAME_PATTERN?=.* + +.PHONY: integration-test +integration-test: $(XUNIT_INTEGRATION_XML) ## Start integration tests + +.PHONY: start-local-docker-compose +start-local-docker-compose: +ifeq ($(ENVIRONMENT), local) + echo "Found developer environment. Starting up docker-compose" + docker-compose up -d +else + echo "Found CI environment. Use existing docker configuration" +endif + + +.PHONY: stop-local-docker-compose +stop-local-docker-compose: +ifeq ($(ENVIRONMENT), local) + echo "Found developer environment. Quitting docker-compose" + docker-compose kill; +else + echo "Found CI environment. Nothing to be done" +endif + +$(XUNIT_INTEGRATION_XML): $(SRC) $(GO_JUNIT_REPORT) +ifneq ($(strip $(PRE_INTEGRATIONTESTS)),) + @make $(PRE_INTEGRATIONTESTS) +endif + + @mkdir -p $(INTEGRATION_TEST_DIR) + @echo 'mode: set' > $(INTEGRATION_TEST_REPORT) + @rm -f $(INTEGRATION_TEST_LOG) || true + @$(GO_CALL) test ./... -v -tags=${GO_BUILD_TAG_INTEGRATION_TEST} -coverpkg=./... -coverprofile=${INTEGRATION_TEST_REPORT} -run ${INTEGRATION_TEST_NAME_PATTERN} 2>&1 | tee $(INTEGRATION_TEST_LOG) + @cat $(INTEGRATION_TEST_LOG) | $(GO_JUNIT_REPORT) > $@ + @if grep '^FAIL' $(INTEGRATION_TEST_LOG); then \ + exit 1; \ + fi + +ifneq ($(strip $(POST_INTEGRATIONTESTS)),) + @make $(POST_INTEGRATIONTESTS) +endif diff --git a/build/make/test-unit.mk b/build/make/test-unit.mk new file mode 100644 index 0000000..6838b1c --- /dev/null +++ b/build/make/test-unit.mk @@ -0,0 +1,36 @@ +##@ Unit testing + +UNIT_TEST_DIR=$(TARGET_DIR)/unit-tests +XUNIT_XML=$(UNIT_TEST_DIR)/unit-tests.xml +UNIT_TEST_LOG=$(UNIT_TEST_DIR)/unit-tests.log +COVERAGE_REPORT=$(UNIT_TEST_DIR)/coverage.out + +PRE_UNITTESTS?= +POST_UNITTESTS?= + +.PHONY: unit-test +unit-test: $(XUNIT_XML) ## Start unit tests + +$(XUNIT_XML): $(SRC) $(GO_JUNIT_REPORT) +ifneq ($(strip $(PRE_UNITTESTS)),) + @make $(PRE_UNITTESTS) +endif + + @mkdir -p $(UNIT_TEST_DIR) + @echo 'mode: set' > ${COVERAGE_REPORT} + @rm -f $(UNIT_TEST_LOG) || true + @for PKG in $(PACKAGES) ; do \ + ${GO_CALL} test -v $$PKG -coverprofile=${COVERAGE_REPORT}.tmp 2>&1 | tee $(UNIT_TEST_LOG).tmp ; \ + cat ${COVERAGE_REPORT}.tmp | tail +2 >> ${COVERAGE_REPORT} ; \ + rm -f ${COVERAGE_REPORT}.tmp ; \ + cat $(UNIT_TEST_LOG).tmp >> $(UNIT_TEST_LOG) ; \ + rm -f $(UNIT_TEST_LOG).tmp ; \ + done + @cat $(UNIT_TEST_LOG) | $(GO_JUNIT_REPORT) > $@ + @if grep '^FAIL' $(UNIT_TEST_LOG); then \ + exit 1; \ + fi + +ifneq ($(strip $(POST_UNITTESTS)),) + @make $(POST_UNITTESTS) +endif diff --git a/build/make/variables.mk b/build/make/variables.mk new file mode 100644 index 0000000..964130e --- /dev/null +++ b/build/make/variables.mk @@ -0,0 +1,93 @@ +TARGET_DIR=target + +WORKDIR:=$(shell pwd) +BUILD_DIR=$(WORKDIR)/build +TMP_DIR:=$(BUILD_DIR)/tmp + +BINARY:=$(TARGET_DIR)/$(ARTIFACT_ID) + +COMMIT_ID:=$(shell git rev-parse HEAD) +LAST_COMMIT_DATE=$(shell git rev-list --format=format:'%ci' --max-count=1 `git rev-parse HEAD` | tail -1) +TAR_ARGS:=--owner=0:0 --group=0:0 --mtime="$(LAST_COMMIT_DATE)" --sort=name +BRANCH=$(shell git branch | grep \* | sed 's/ /\n/g' | head -2 | tail -1) + +GO_ENVIRONMENT?= +# GO_CALL accomodates the go CLI command as well as necessary environment variables which are optional. +GO_CALL=${GO_ENVIRONMENT} go +PACKAGES=$(shell ${GO_CALL} list ./... | grep -v /vendor/) +GO_BUILD_TAG_INTEGRATION_TEST?=integration +GOMODULES=on +UTILITY_BIN_PATH?=${WORKDIR}/.bin + +SRC:=$(shell find "${WORKDIR}" -type f -name "*.go" -not -path "./vendor/*") + +# debian stuff +DEBIAN_BUILD_DIR=$(BUILD_DIR)/deb +DEBIAN_CONTENT_DIR=$(DEBIAN_BUILD_DIR)/content +DEBIAN_PACKAGE=$(TARGET_DIR)/$(ARTIFACT_ID)_$(VERSION).deb +APT_API_BASE_URL=https://apt-api.cloudogu.com/api + +# choose the environment, if BUILD_URL environment variable is available then we are on ci (jenkins) +ifdef BUILD_URL +ENVIRONMENT=ci +else +ENVIRONMENT=local +endif + +YARN_TARGET=$(WORKDIR)/node_modules +BOWER_TARGET?=$(WORKDIR)/public/vendor +NODE_VERSION?=8 + +UID_NR:=$(shell id -u) +GID_NR:=$(shell id -g) +HOME_DIR=$(TMP_DIR)/home +PASSWD=$(TMP_DIR)/passwd +ETCGROUP=$(TMP_DIR)/group + +$(TMP_DIR): + @mkdir -p $(TMP_DIR) + +$(HOME_DIR): $(TMP_DIR) + @mkdir -p $(HOME_DIR) + +$(TARGET_DIR): + @mkdir -p $(TARGET_DIR) + +$(PASSWD): $(TMP_DIR) + @echo "$(USER):x:$(UID_NR):$(GID_NR):$(USER):/home/$(USER):/bin/bash" > $(PASSWD) + +$(ETCGROUP): $(TMP_DIR) + @echo "root:x:0:" > $(ETCGROUP) + @echo "$(USER):x:$(GID_NR):" >> $(ETCGROUP) + +$(UTILITY_BIN_PATH): + @mkdir -p $@ + +##@ General + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +.PHONY: info +info: ## Print build information + @echo "dumping build information ..." + @echo "Version : $(VERSION)" + @echo "Commit-ID : $(COMMIT_ID)" + @echo "Environment: $(ENVIRONMENT)" + @echo "Branch : $(BRANCH)" + @echo "Packages : $(PACKAGES)" + + +# go-get-tool will 'go get' any package $2 and install it to $1. +define go-get-tool + @[ -f $(1) ] || { \ + set -e ;\ + TMP_DIR=$$(mktemp -d) ;\ + cd $$TMP_DIR ;\ + go mod init tmp ;\ + echo "Downloading $(2)" ;\ + GOBIN=$(UTILITY_BIN_PATH) go install $(2) ;\ + rm -rf $$TMP_DIR ;\ + } +endef diff --git a/build/make/yarn.mk b/build/make/yarn.mk new file mode 100644 index 0000000..12792b4 --- /dev/null +++ b/build/make/yarn.mk @@ -0,0 +1,27 @@ +##@ Yarn dependency management + +YARN_LOCK=$(WORKDIR)/yarn.lock + +.PHONY: yarn-install +yarn-install: $(YARN_TARGET) ## Execute yarn install + +ifeq ($(ENVIRONMENT), ci) + +$(YARN_TARGET): $(YARN_LOCK) + @echo "Yarn install on CI server" + @yarn install + +else + +$(YARN_TARGET): $(YARN_LOCK) $(PASSWD) + @echo "Executing yarn..." + @docker run --rm \ + -u "$(UID_NR):$(GID_NR)" \ + -v $(PASSWD):/etc/passwd:ro \ + -v $(WORKDIR):$(WORKDIR) \ + -w $(WORKDIR) \ + node:$(NODE_VERSION) \ + yarn install + @touch $@ + +endif diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml new file mode 100644 index 0000000..77f205f --- /dev/null +++ b/config/default/kustomization.yaml @@ -0,0 +1,70 @@ +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: k8s-backup-operator- + +bases: +- ../rbac +- ../manager +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- ../webhook +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +#- ../certmanager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: +# Protect the /metrics endpoint by putting it behind auth. +# If you want your controller-manager to expose the /metrics +# endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml + +# Mount the controller config file for loading manager configurations +# through a ComponentConfig type +#- manager_config_patch.yaml + +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- manager_webhook_patch.yaml + +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +#- webhookcainjection_patch.yaml + +# the following config is for teaching kustomize how to do var substitution +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 0000000..7ae9a4b --- /dev/null +++ b/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,33 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager +spec: + template: + spec: + containers: + - name: kube-rbac-proxy + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=0" + ports: + - containerPort: 8443 + protocol: TCP + name: https + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + - name: manager + args: + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml new file mode 100644 index 0000000..e846a37 --- /dev/null +++ b/config/default/manager_config_patch.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager +spec: + template: + spec: + containers: + - name: manager + args: + - "--config=controller_manager_config.yaml" + volumeMounts: + - name: manager-config + mountPath: /controller_manager_config.yaml + subPath: controller_manager_config.yaml + volumes: + - name: manager-config + configMap: + name: manager-config diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml new file mode 100644 index 0000000..8249a38 --- /dev/null +++ b/config/manager/controller_manager_config.yaml @@ -0,0 +1,11 @@ +apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 +kind: ControllerManagerConfig +health: + healthProbeBindAddress: :8081 +metrics: + bindAddress: 127.0.0.1:8080 +webhook: + port: 9443 +leaderElection: + leaderElect: true + resourceName: 951e217a.cloudogu.com diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml new file mode 100644 index 0000000..5da3c8b --- /dev/null +++ b/config/manager/kustomization.yaml @@ -0,0 +1,14 @@ +resources: +- manager.yaml +generatorOptions: + disableNameSuffixHash: true +configMapGenerator: +- files: + - controller_manager_config.yaml + name: manager-config +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: cloudogu/k8s-backup-operator + newTag: 0.19.0 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml new file mode 100644 index 0000000..b9a6fc7 --- /dev/null +++ b/config/manager/manager.yaml @@ -0,0 +1,90 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + labels: + control-plane: controller-manager +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + strategy: + type: Recreate + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: controller-manager + app.kubernetes.io/name: k8s-backup-operator + app: ces + spec: + securityContext: + runAsNonRoot: true + containers: + - args: + - --leader-elect + env: + - name: STAGE + value: "production" + - name: LOG_LEVEL + value: "debug" + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: DOGU_REGISTRY_ENDPOINT + valueFrom: + secretKeyRef: + name: k8s-backup-operator-dogu-registry + key: endpoint + - name: DOGU_REGISTRY_USERNAME + valueFrom: + secretKeyRef: + name: k8s-backup-operator-dogu-registry + key: username + - name: DOGU_REGISTRY_PASSWORD + valueFrom: + secretKeyRef: + name: k8s-backup-operator-dogu-registry + key: password + - name: DOGU_REGISTRY_URLSCHEMA + valueFrom: + secretKeyRef: + name: k8s-backup-operator-dogu-registry + key: urlschema + optional: true + - name: DOCKER_REGISTRY + valueFrom: + secretKeyRef: + name: k8s-backup-operator-docker-registry + key: .dockerconfigjson + image: controller:latest + imagePullPolicy: IfNotPresent + name: manager + securityContext: + allowPrivilegeEscalation: false + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + # TODO(user): Configure the resources accordingly based on the project requirements. + # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 diff --git a/config/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml new file mode 100644 index 0000000..ed13716 --- /dev/null +++ b/config/prometheus/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- monitor.yaml diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml new file mode 100644 index 0000000..d19136a --- /dev/null +++ b/config/prometheus/monitor.yaml @@ -0,0 +1,20 @@ + +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-monitor + namespace: system +spec: + endpoints: + - path: /metrics + port: https + scheme: https + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + tlsConfig: + insecureSkipVerify: true + selector: + matchLabels: + control-plane: controller-manager diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 0000000..b19981f --- /dev/null +++ b/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: + - nonResourceURLs: + - "/metrics" + verbs: + - get \ No newline at end of file diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml new file mode 100644 index 0000000..0e91929 --- /dev/null +++ b/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 0000000..5ee85d5 --- /dev/null +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: proxy-role +subjects: +- kind: ServiceAccount + name: controller-manager diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml new file mode 100644 index 0000000..c54a533 --- /dev/null +++ b/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: controller-manager diff --git a/config/rbac/cluster_role.yaml b/config/rbac/cluster_role.yaml new file mode 100644 index 0000000..b55de59 --- /dev/null +++ b/config/rbac/cluster_role.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cluster-role + labels: + app: k8s-backup-operator + app.kubernetes.io/name: k8s-backup-operator +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + verbs: + - "*" \ No newline at end of file diff --git a/config/rbac/cluster_role_binding.yaml b/config/rbac/cluster_role_binding.yaml new file mode 100644 index 0000000..8c616f5 --- /dev/null +++ b/config/rbac/cluster_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cluster-role-binding + labels: + app: k8s-backup-operator + app.kubernetes.io/name: k8s-backup-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: k8s-backup-operator-cluster-role +subjects: + - kind: ServiceAccount + name: k8s-backup-operator-controller-manager + namespace: '{{ .Namespace }}' diff --git a/config/rbac/dogu_editor_role.yaml b/config/rbac/dogu_editor_role.yaml new file mode 100644 index 0000000..84999fb --- /dev/null +++ b/config/rbac/dogu_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit dogus. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: dogu-editor-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - dogus + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - dogus/status + verbs: + - get diff --git a/config/rbac/dogu_viewer_role.yaml b/config/rbac/dogu_viewer_role.yaml new file mode 100644 index 0000000..184626c --- /dev/null +++ b/config/rbac/dogu_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view dogus. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: dogu-viewer-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - dogus + verbs: + - get + - list + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - dogus/status + verbs: + - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml new file mode 100644 index 0000000..f1144cc --- /dev/null +++ b/config/rbac/kustomization.yaml @@ -0,0 +1,20 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- cluster_role.yaml +- cluster_role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml new file mode 100644 index 0000000..4190ec8 --- /dev/null +++ b/config/rbac/leader_election_role.yaml @@ -0,0 +1,37 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 0000000..df9defb --- /dev/null +++ b/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: controller-manager diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml new file mode 100644 index 0000000..11b5244 --- /dev/null +++ b/config/rbac/role.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: manager-role +rules: +- apiGroups: + - "*" + resources: + - "*" + verbs: + - "*" diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml new file mode 100644 index 0000000..5e11a2f --- /dev/null +++ b/config/rbac/role_binding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: manager-role +subjects: +- kind: ServiceAccount + name: controller-manager diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml new file mode 100644 index 0000000..69ece2e --- /dev/null +++ b/config/rbac/service_account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: controller-manager diff --git a/config/samples/cas_config.sh b/config/samples/cas_config.sh new file mode 100644 index 0000000..d49a7df --- /dev/null +++ b/config/samples/cas_config.sh @@ -0,0 +1,10 @@ +kubectl exec -it etcd-client -- etcdctl set "config/cas/ldap/ds_type" "embedded" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_id" "uid" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_group" "memberof" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_mail" "mail" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/search_filter" "(objectClass=person)" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_fullname" "cn" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/encryption" "none" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/host" "ldap" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/port" "389" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/logging/root" "DEBUG" \ No newline at end of file diff --git a/config/samples/hallowelt/bluespice-pdfrenderer.yaml b/config/samples/hallowelt/bluespice-pdfrenderer.yaml new file mode 100644 index 0000000..0150b03 --- /dev/null +++ b/config/samples/hallowelt/bluespice-pdfrenderer.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: bluespice-pdfrenderer + annotations: + test: dev + labels: + dogu.name: bluespice-pdfrenderer + app: ces +spec: + name: hallowelt/bluespice-pdfrenderer + version: 4.2.1-1 \ No newline at end of file diff --git a/config/samples/hallowelt/bluespice.yaml b/config/samples/hallowelt/bluespice.yaml new file mode 100644 index 0000000..919d4da --- /dev/null +++ b/config/samples/hallowelt/bluespice.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: bluespice + annotations: + test: dev + labels: + dogu.name: bluespice + app: ces +spec: + name: hallowelt/bluespice + version: 4.2.3-2 \ No newline at end of file diff --git a/config/samples/hallowelt/drawio.yaml b/config/samples/hallowelt/drawio.yaml new file mode 100644 index 0000000..36181bc --- /dev/null +++ b/config/samples/hallowelt/drawio.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: drawio + annotations: + test: dev + labels: + dogu.name: drawio + app: ces +spec: + name: hallowelt/drawio + version: 20.3.7-1 \ No newline at end of file diff --git a/config/samples/itz-bund/teamscale.yaml b/config/samples/itz-bund/teamscale.yaml new file mode 100644 index 0000000..2ef4e3f --- /dev/null +++ b/config/samples/itz-bund/teamscale.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: teamscale + annotations: + test: dev + labels: + dogu.name: teamscale + app: ces +spec: + name: itz-bund/teamscale + version: 8.4.0-1 \ No newline at end of file diff --git a/config/samples/k8s/nginx-ingress.yaml b/config/samples/k8s/nginx-ingress.yaml new file mode 100644 index 0000000..7c57897 --- /dev/null +++ b/config/samples/k8s/nginx-ingress.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: nginx-ingress + annotations: + test: dev + labels: + dogu.name: nginx-ingress + app: nginx-ingress +spec: + name: k8s/nginx-ingress + version: 1.3.0-2 \ No newline at end of file diff --git a/config/samples/k8s/nginx-static.yaml b/config/samples/k8s/nginx-static.yaml new file mode 100644 index 0000000..812d702 --- /dev/null +++ b/config/samples/k8s/nginx-static.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: nginx-static + annotations: + test: dev + labels: + dogu.name: nginx-static + app: nginx-static +spec: + name: k8s/nginx-static + version: 1.23.1-3 \ No newline at end of file diff --git a/config/samples/k8s_v1_dogu.yaml b/config/samples/k8s_v1_dogu.yaml new file mode 100644 index 0000000..bf9a550 --- /dev/null +++ b/config/samples/k8s_v1_dogu.yaml @@ -0,0 +1,8 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: dogu-sample +spec: + name: official/postfix + version: 3.6.4-3 + supportMode: false \ No newline at end of file diff --git a/config/samples/ldap-mapper.sh b/config/samples/ldap-mapper.sh new file mode 100644 index 0000000..ec963aa --- /dev/null +++ b/config/samples/ldap-mapper.sh @@ -0,0 +1,3 @@ +kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/type" "embedded" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/host" "ldap" \ +&& kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/port" "389" \ No newline at end of file diff --git a/config/samples/ldap_config.sh b/config/samples/ldap_config.sh new file mode 100644 index 0000000..1c8637d --- /dev/null +++ b/config/samples/ldap_config.sh @@ -0,0 +1,2 @@ +kubectl exec -it etcd-client -- etcdctl set "config/ldap/admin_mail" "mail@test.de" \ +&& kubectl exec -it etcd-client -- etcdctl set "config/ldap/admin_member" "true" \ No newline at end of file diff --git a/config/samples/official/backup.yaml b/config/samples/official/backup.yaml new file mode 100644 index 0000000..96e66a5 --- /dev/null +++ b/config/samples/official/backup.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: backup + annotations: + test: dev + labels: + dogu.name: backup + app: backup +spec: + name: premium/backup + version: 1.9.2-2 \ No newline at end of file diff --git a/config/samples/official/cas.yaml b/config/samples/official/cas.yaml new file mode 100644 index 0000000..85057a8 --- /dev/null +++ b/config/samples/official/cas.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: cas + annotations: + test: dev + labels: + dogu.name: cas + app: ces +spec: + name: official/cas + version: 6.5.5-4 \ No newline at end of file diff --git a/config/samples/official/cas_config.sh b/config/samples/official/cas_config.sh new file mode 100755 index 0000000..5fcb39b --- /dev/null +++ b/config/samples/official/cas_config.sh @@ -0,0 +1,10 @@ +kubectl exec --namespace ecosystem etcd-client -- etcdctl set "config/cas/ldap/ds_type" "embedded" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_id" "uid" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_group" "memberof" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_mail" "mail" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/search_filter" "(objectClass=person)" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_fullname" "cn" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/encryption" "none" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/host" "ldap" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/port" "389" \ +&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/logging/root" "DEBUG" \ No newline at end of file diff --git a/config/samples/official/cockpit.yaml b/config/samples/official/cockpit.yaml new file mode 100644 index 0000000..1da3de6 --- /dev/null +++ b/config/samples/official/cockpit.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: cockpit + annotations: + test: dev + labels: + dogu.name: cockpit + app: ces +spec: + name: official/cockpit + version: 2.0.2-5 \ No newline at end of file diff --git a/config/samples/official/elasticsearch.yaml b/config/samples/official/elasticsearch.yaml new file mode 100644 index 0000000..6c50f6e --- /dev/null +++ b/config/samples/official/elasticsearch.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: elasticsearch + annotations: + test: dev + labels: + dogu.name: drawio + app: elasticsearch +spec: + name: official/elasticsearch + version: 6.8.23-3 \ No newline at end of file diff --git a/config/samples/official/gotenberg.yaml b/config/samples/official/gotenberg.yaml new file mode 100644 index 0000000..a061817 --- /dev/null +++ b/config/samples/official/gotenberg.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: gotenberg + annotations: + test: dev + labels: + dogu.name: gotenberg + app: ces +spec: + name: official/gotenberg + version: 7.5.2-1 \ No newline at end of file diff --git a/config/samples/official/jenkins.yaml b/config/samples/official/jenkins.yaml new file mode 100644 index 0000000..6697ad4 --- /dev/null +++ b/config/samples/official/jenkins.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: jenkins + annotations: + test: dev + labels: + dogu.name: jenkins + app: ces +spec: + name: official/jenkins + version: 2.346.1-1 \ No newline at end of file diff --git a/config/samples/official/ldap-mapper.sh b/config/samples/official/ldap-mapper.sh new file mode 100755 index 0000000..578faef --- /dev/null +++ b/config/samples/official/ldap-mapper.sh @@ -0,0 +1,3 @@ +kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/type" "embedded" \ +&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/host" "ldap" \ +&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/port" "389" \ No newline at end of file diff --git a/config/samples/official/ldap-mapper.yaml b/config/samples/official/ldap-mapper.yaml new file mode 100644 index 0000000..9f59ce4 --- /dev/null +++ b/config/samples/official/ldap-mapper.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: ldap-mapper + annotations: + test: dev + labels: + dogu.name: ldap-mapper + app: ces +spec: + name: official/ldap-mapper + version: 1.3.0 \ No newline at end of file diff --git a/config/samples/official/ldap.yaml b/config/samples/official/ldap.yaml new file mode 100644 index 0000000..586d894 --- /dev/null +++ b/config/samples/official/ldap.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: ldap + annotations: + test: dev + labels: + dogu.name: ldap + app: ces +spec: + name: official/ldap + version: 2.6.2-2 \ No newline at end of file diff --git a/config/samples/official/ldap_config.sh b/config/samples/official/ldap_config.sh new file mode 100755 index 0000000..d5f2a73 --- /dev/null +++ b/config/samples/official/ldap_config.sh @@ -0,0 +1,2 @@ +kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/ldap/admin_mail" "mail@test.de" \ +&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/ldap/admin_member" "true" \ No newline at end of file diff --git a/config/samples/official/mysql.yaml b/config/samples/official/mysql.yaml new file mode 100644 index 0000000..99407e0 --- /dev/null +++ b/config/samples/official/mysql.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: mysql + annotations: + test: dev + labels: + dogu.name: mysql + app: ces +spec: + name: official/mysql + version: 5.7.37-4 \ No newline at end of file diff --git a/config/samples/official/nexus.yaml b/config/samples/official/nexus.yaml new file mode 100644 index 0000000..0158e4f --- /dev/null +++ b/config/samples/official/nexus.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: nexus + annotations: + test: dev + labels: + dogu.name: nexus + app: ces +spec: + name: official/nexus + version: 3.40.1-2 \ No newline at end of file diff --git a/config/samples/official/plantuml.yaml b/config/samples/official/plantuml.yaml new file mode 100644 index 0000000..56ef277 --- /dev/null +++ b/config/samples/official/plantuml.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: plantuml + annotations: + test: dev + labels: + dogu.name: plantuml + app: ces +spec: + name: official/plantuml + version: 2022.4-1 \ No newline at end of file diff --git a/config/samples/official/postfix.yaml b/config/samples/official/postfix.yaml new file mode 100644 index 0000000..fd2801a --- /dev/null +++ b/config/samples/official/postfix.yaml @@ -0,0 +1,14 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: postfix + annotations: + test: dev + labels: + dogu.name: postfix + app: ces +spec: + name: official/postfix + version: 3.6.4-3 + resources: + dataVolumeSize: "4Gi" diff --git a/config/samples/official/postfix_config.sh b/config/samples/official/postfix_config.sh new file mode 100755 index 0000000..65a70a6 --- /dev/null +++ b/config/samples/official/postfix_config.sh @@ -0,0 +1 @@ +kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/postfix/relayhost" "mail.mydomain.com" \ No newline at end of file diff --git a/config/samples/official/postgresql.yaml b/config/samples/official/postgresql.yaml new file mode 100644 index 0000000..9d50d76 --- /dev/null +++ b/config/samples/official/postgresql.yaml @@ -0,0 +1,14 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: postgresql + annotations: + test: dev + labels: + dogu.name: postgresql + app: ces +spec: + name: official/postgresql + version: 12.10-1 + resources: + dataVolumeSize: "1Gi" diff --git a/config/samples/official/redis.yaml b/config/samples/official/redis.yaml new file mode 100644 index 0000000..10858a1 --- /dev/null +++ b/config/samples/official/redis.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: redis + annotations: + test: dev + labels: + dogu.name: redis + app: ces +spec: + name: official/redis + version: 6.2.6-2 \ No newline at end of file diff --git a/config/samples/official/redmine.yaml b/config/samples/official/redmine.yaml new file mode 100644 index 0000000..899829e --- /dev/null +++ b/config/samples/official/redmine.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: redmine + annotations: + test: dev + labels: + dogu.name: redmine + app: ces +spec: + name: official/redmine + version: 4.2.5-1 \ No newline at end of file diff --git a/config/samples/official/scm.yaml b/config/samples/official/scm.yaml new file mode 100644 index 0000000..8c739dd --- /dev/null +++ b/config/samples/official/scm.yaml @@ -0,0 +1,13 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: scm + annotations: + test: dev + labels: + dogu.name: scm + app: ces +spec: + name: official/scm + version: 2.40.0-1 +# version: 2.39.1-1 \ No newline at end of file diff --git a/config/samples/official/smeagol.yaml b/config/samples/official/smeagol.yaml new file mode 100644 index 0000000..ccf011d --- /dev/null +++ b/config/samples/official/smeagol.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: smeagol + annotations: + test: dev + labels: + dogu.name: smeagol + app: ces +spec: + name: official/smeagol + version: 1.6.2-2 \ No newline at end of file diff --git a/config/samples/official/sonar.yaml b/config/samples/official/sonar.yaml new file mode 100644 index 0000000..ddce5fc --- /dev/null +++ b/config/samples/official/sonar.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: sonar + annotations: + test: dev + labels: + dogu.name: sonar + app: ces +spec: + name: official/sonar + version: 8.9.8-2 \ No newline at end of file diff --git a/config/samples/official/swaggerui.yaml b/config/samples/official/swaggerui.yaml new file mode 100644 index 0000000..b1e923f --- /dev/null +++ b/config/samples/official/swaggerui.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: swaggerui + annotations: + test: dev + labels: + dogu.name: swaggerui + app: ces +spec: + name: official/swaggerui + version: 4.9.0-1 \ No newline at end of file diff --git a/config/samples/official/usermgt.yaml b/config/samples/official/usermgt.yaml new file mode 100644 index 0000000..c43ceaa --- /dev/null +++ b/config/samples/official/usermgt.yaml @@ -0,0 +1,14 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: usermgt + annotations: + test: dev + labels: + dogu.name: usermgt + app: ces +spec: + name: official/usermgt + version: 1.7.0-1 + resources: + dataVolumeSize: "6Gi" \ No newline at end of file diff --git a/config/samples/postfix_config.sh b/config/samples/postfix_config.sh new file mode 100644 index 0000000..a2f5fe8 --- /dev/null +++ b/config/samples/postfix_config.sh @@ -0,0 +1 @@ +kubectl exec -it etcd-client -- etcdctl set "config/postfix/relayhost" "mail.mydomain.com" \ No newline at end of file diff --git a/config/samples/premium/admin.yaml b/config/samples/premium/admin.yaml new file mode 100644 index 0000000..cb4b98a --- /dev/null +++ b/config/samples/premium/admin.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: admin + annotations: + test: dev + labels: + dogu.name: admin + app: ces +spec: + name: premium/admin + version: 2.6.2-1 \ No newline at end of file diff --git a/config/samples/premium/confluence.yaml b/config/samples/premium/confluence.yaml new file mode 100644 index 0000000..ec1795e --- /dev/null +++ b/config/samples/premium/confluence.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: confluence + annotations: + test: dev + labels: + dogu.name: confluence + app: ces +spec: + name: premium/confluence + version: 7.13.8-1 \ No newline at end of file diff --git a/config/samples/premium/jira.yaml b/config/samples/premium/jira.yaml new file mode 100644 index 0000000..f1388ae --- /dev/null +++ b/config/samples/premium/jira.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Dogu +metadata: + name: jira + annotations: + test: dev + labels: + dogu.name: jira + app: ces +spec: + name: premium/jira + version: 8.20.13-1 \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5a949d7 --- /dev/null +++ b/go.mod @@ -0,0 +1,107 @@ +module github.com/cloudogu/k8s-backup-operator + +go 1.18 + +require ( + github.com/bombsimon/logrusr/v2 v2.0.1 + github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473 + github.com/cloudogu/k8s-apply-lib v0.4.0 + github.com/go-logr/logr v1.2.3 + github.com/google/go-cmp v0.5.8 + github.com/google/go-containerregistry v0.8.0 + github.com/hashicorp/go-multierror v1.1.1 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.19.0 + github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.9.0 + github.com/stretchr/testify v1.8.1 + go.etcd.io/etcd/client/v2 v2.305.4 + golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c + k8s.io/api v0.24.4 + k8s.io/apimachinery v0.24.4 + k8s.io/client-go v0.24.4 + k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 + sigs.k8s.io/controller-runtime v0.12.3 + sigs.k8s.io/yaml v1.3.0 +) + +replace google.golang.org/grpc => google.golang.org/grpc v1.29.0 + +require ( + cloud.google.com/go/compute v1.9.0 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.28 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.10.1 // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/docker/cli v20.10.12+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker v20.10.12+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.4 // indirect + github.com/eapache/go-resiliency v1.3.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.13.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/vbatts/tar-split v0.11.2 // indirect + go.etcd.io/etcd/api/v3 v3.5.4 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect + golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect + golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect + golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect + golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect + golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.24.4 // indirect + k8s.io/component-base v0.24.4 // indirect + k8s.io/klog/v2 v2.70.1 // indirect + k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f9eda69 --- /dev/null +++ b/go.sum @@ -0,0 +1,1588 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.9.0 h1:ED/FP4xv8GJw63v556/ASNc1CeeLUO2Bs8nzaHchkHg= +cloud.google.com/go/compute v1.9.0/go.mod h1:lWv1h/zUWTm/LozzfTJhBSkd6ShQq8la8VeeuOEGxfY= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +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= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +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.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= +github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= +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/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= +github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= +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.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +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/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +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= +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/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +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/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= +github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473 h1:cRZXYR4/bd+IUlBXnmlVj3kOQiluqJtwCpBiTgO6cCg= +github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473/go.mod h1:PTQqI3xs1ReJMXYE6BGTF33yAfmS4J7P8UiE4AwDMDY= +github.com/cloudogu/k8s-apply-lib v0.4.0 h1:4jYj0gTDSvW0qs9d5yM5w8aOsMu5Sx+PBCwJwa5sMss= +github.com/cloudogu/k8s-apply-lib v0.4.0/go.mod h1:WHCe588o8e1vzNdLGV6N4E0g7BarbPXPpW4y8U0/lxE= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng= +github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +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/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +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/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +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= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= +github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U= +github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +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/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/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0= +github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= +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= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +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/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= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.0.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= +github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/protobuf v1.1.1/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.0/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= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= +github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.8.0 h1:mtR24eN6rapCN+shds82qFEIWWmg64NPMuyCNT7/Ogc= +github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= +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= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +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/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +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/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +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.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +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= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +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.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +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/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= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/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/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/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +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/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +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/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +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-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.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.10.3/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.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +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= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= +github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +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/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +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/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +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/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +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.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/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= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +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= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +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/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= +go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +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.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +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.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-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-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +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= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c= +golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20181011144130-49bb7cea24b1/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= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes= +golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 h1:2o1E+E8TpNLklK9nHiPiK1uzIYrIHt+cQx3ynCwq9V8= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/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-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= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= +golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +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-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= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +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-20141024133853-64131543e789/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +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.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +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= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/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= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +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/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= +k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= +k8s.io/apiextensions-apiserver v0.24.4 h1:w53Pm4zu8fCt9WfiRgS2YI6LE6I4NJ5aUi78GElD3K8= +k8s.io/apiextensions-apiserver v0.24.4/go.mod h1:iDK+Xb4jsPNnRGj5jU/WqqjLvt8363M7cKixKe1C9+U= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= +k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/apiserver v0.24.4/go.mod h1:mAuC3pZVc0IDXLx7lUHoisBOtBa1SobfLW/CI3klXQE= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= +k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= +k8s.io/code-generator v0.24.4/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/component-base v0.24.4 h1:WEGRp06GBYVwxp5JdiRaJ1zkdOhrqucxRv/8IrABLG0= +k8s.io/component-base v0.24.4/go.mod h1:sWxkgcMfbYHadw0OJ0N+vIscd14/nqSIM2veCdg843o= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +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.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= +k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea h1:3QOH5+2fGsY8e1qf+GIFpg+zw/JGNrgyZRQR7/m6uWg= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 h1:XmRqFcQlCy/lKRZ39j+RVpokYNroHPqV3mcBRfnhT5o= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +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.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/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= +sigs.k8s.io/controller-runtime v0.12.3 h1:FCM8xeY/FI8hoAfh/V4XbbYMY20gElh9yh+A98usMio= +sigs.k8s.io/controller-runtime v0.12.3/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt new file mode 100644 index 0000000..66a6d0a --- /dev/null +++ b/hack/boilerplate.go.txt @@ -0,0 +1,3 @@ +/* +This file was generated with "make generate". +*/ \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..4864d5b --- /dev/null +++ b/main.go @@ -0,0 +1,149 @@ +package main + +import ( + "flag" + "fmt" + "github.com/cloudogu/k8s-backup-operator/pkg/config" + "github.com/cloudogu/k8s-backup-operator/pkg/controllers" + "github.com/cloudogu/k8s-backup-operator/pkg/logging" + "os" + + "sigs.k8s.io/controller-runtime/pkg/manager" + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + // +kubebuilder:scaffold:imports +) + +var ( + scheme = runtime.NewScheme() + // set up the logger before the actual logger is instantiated + // the logger will be replaced later-on with a more sophisticated instance + setupLog = ctrl.Log.WithName("setup") + metricsAddr string + enableLeaderElection bool + probeAddr string +) + +var ( + // Version of the application + Version = "0.0.0" +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + // +kubebuilder:scaffold:scheme +} + +func main() { + err := startOperator() + if err != nil { + setupLog.Error(err, "failed to start operator") + os.Exit(1) + } +} + +func startOperator() error { + err := logging.ConfigureLogger() + if err != nil { + return err + } + + operatorConfig, err := config.NewOperatorConfig(Version) + if err != nil { + return fmt.Errorf("failed to create new operator configuration: %w", err) + } + + options := getK8sManagerOptions(operatorConfig) + k8sManager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) + if err != nil { + return fmt.Errorf("failed to start manager: %w", err) + } + + err = configureManager(k8sManager, operatorConfig) + if err != nil { + return fmt.Errorf("failed to configure manager: %w", err) + } + + // print starting info to stderr; we don't use the logger here because by default the level must be ERROR + println("Starting manager...") + + return startK8sManager(k8sManager) +} + +func configureManager(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { + err := configureReconciler(k8sManager, operatorConfig) + if err != nil { + return fmt.Errorf("failed to configure reconciler: %w", err) + } + + // +kubebuilder:scaffold:builder + err = addChecks(k8sManager) + if err != nil { + return fmt.Errorf("failed to add checks to the manager: %w", err) + } + + return nil +} + +func getK8sManagerOptions(operatorConfig *config.OperatorConfig) manager.Options { + flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + + options := ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + Namespace: operatorConfig.Namespace, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "951e217a.cloudogu.com", + } + + return options +} + +func startK8sManager(k8sManager manager.Manager) error { + setupLog.Info("starting manager") + err := k8sManager.Start(ctrl.SetupSignalHandler()) + if err != nil { + return fmt.Errorf("failed to start manager: %w", err) + } + + return nil +} + +func configureReconciler(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { + eventRecorder := k8sManager.GetEventRecorderFor("k8s-backup-operator") + backupReconciler := controllers.NewBackupReconciler(k8sManager.GetClient(), eventRecorder) + + err := backupReconciler.SetupWithManager(k8sManager) + if err != nil { + return fmt.Errorf("failed to setup reconciler with manager: %w", err) + } + + return nil +} + +func addChecks(mgr manager.Manager) error { + err := mgr.AddHealthzCheck("healthz", healthz.Ping) + if err != nil { + return fmt.Errorf("failed to add healthz check: %w", err) + } + + err = mgr.AddReadyzCheck("readyz", healthz.Ping) + if err != nil { + return fmt.Errorf("failed to add readyz check: %w", err) + } + + return nil +} diff --git a/main_internal_test.go b/main_internal_test.go new file mode 100644 index 0000000..ed89e92 --- /dev/null +++ b/main_internal_test.go @@ -0,0 +1,165 @@ +package main + +import ( + "context" + "flag" + "fmt" + + "os" + "testing" + + "github.com/cloudogu/k8s-backup-operator/pkg/mocks/external" + + "github.com/go-logr/logr" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +type mockDefinition struct { + Arguments []interface{} + ReturnValue interface{} +} + +func getCopyMap(definitions map[string]mockDefinition) map[string]mockDefinition { + newCopyMap := map[string]mockDefinition{} + for k, v := range definitions { + newCopyMap[k] = v + } + return newCopyMap +} + +func getNewMockManager(expectedErrorOnNewManager error, definitions map[string]mockDefinition) manager.Manager { + k8sManager := &external.Manager{} + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + for key, value := range definitions { + k8sManager.Mock.On(key, value.Arguments...).Return(value.ReturnValue) + } + return k8sManager, expectedErrorOnNewManager + } + ctrl.SetLogger = func(l logr.Logger) { + k8sManager.Mock.On("GetLogger").Return(l) + } + flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + + return k8sManager +} + +func Test_startDoguOperator(t *testing.T) { + // override default controller method to create a new manager + oldNewManagerDelegate := ctrl.NewManager + defer func() { ctrl.NewManager = oldNewManagerDelegate }() + + // override default controller method to retrieve a kube config + oldGetConfigOrDieDelegate := ctrl.GetConfigOrDie + defer func() { ctrl.GetConfigOrDie = oldGetConfigOrDieDelegate }() + ctrl.GetConfigOrDie = func() *rest.Config { + return &rest.Config{} + } + + // override default controller method to retrieve a kube config + oldGetConfigDelegate := ctrl.GetConfig + defer func() { ctrl.GetConfig = oldGetConfigDelegate }() + ctrl.GetConfig = func() (*rest.Config, error) { + return &rest.Config{}, nil + } + + // override default controller method to signal the setup handler + oldHandler := ctrl.SetupSignalHandler + defer func() { ctrl.SetupSignalHandler = oldHandler }() + ctrl.SetupSignalHandler = func() context.Context { + return context.TODO() + } + + // override default controller method to retrieve a kube config + oldSetLoggerDelegate := ctrl.SetLogger + defer func() { ctrl.SetLogger = oldSetLoggerDelegate }() + + scheme := runtime.NewScheme() + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + myClient := fake.NewClientBuilder().WithScheme(scheme).Build() + + defaultMockDefinitions := map[string]mockDefinition{ + "GetScheme": {ReturnValue: scheme}, + "GetClient": {ReturnValue: myClient}, + "Add": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, + "AddHealthzCheck": {Arguments: []interface{}{mock.Anything, mock.Anything}, ReturnValue: nil}, + "AddReadyzCheck": {Arguments: []interface{}{mock.Anything, mock.Anything}, ReturnValue: nil}, + "Start": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, + "GetControllerOptions": {ReturnValue: v1alpha1.ControllerConfigurationSpec{}}, + "SetFields": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, + "GetEventRecorderFor": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, + } + + t.Run("Error on missing namespace environment variable", func(t *testing.T) { + // given + _ = os.Unsetenv("NAMESPACE") + getNewMockManager(nil, defaultMockDefinitions) + + // when + err := startOperator() + + // then + require.Error(t, err) + require.Contains(t, err.Error(), "failed to read namespace: failed to get env var [NAMESPACE]") + }) + + t.Setenv("NAMESPACE", "mynamespace") + t.Run("Test without logger environment variables", func(t *testing.T) { + // given + k8sManager := getNewMockManager(nil, defaultMockDefinitions) + + // when + err := startOperator() + + // then + require.NoError(t, err) + mock.AssertExpectationsForObjects(t, k8sManager) + }) + + expectedError := fmt.Errorf("this is my expected error") + + t.Run("Test with error on manager creation", func(t *testing.T) { + // given + getNewMockManager(expectedError, defaultMockDefinitions) + + // when + err := startOperator() + + // then + require.ErrorIs(t, err, expectedError) + }) + + mockDefinitionsThatCanFail := []string{ + "Add", + "AddHealthzCheck", + "AddReadyzCheck", + "Start", + "SetFields", + } + + for _, mockDefinitionName := range mockDefinitionsThatCanFail { + t.Run(fmt.Sprintf("fail setup when error on %s", mockDefinitionName), func(t *testing.T) { + // given + adaptedMockDefinitions := getCopyMap(defaultMockDefinitions) + adaptedMockDefinitions[mockDefinitionName] = mockDefinition{ + Arguments: adaptedMockDefinitions[mockDefinitionName].Arguments, + ReturnValue: expectedError, + } + getNewMockManager(nil, adaptedMockDefinitions) + + // when + err := startOperator() + + // then + require.ErrorIs(t, err, expectedError) + }) + } +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..0a87bf0 --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,78 @@ +package config + +import ( + "fmt" + "github.com/cloudogu/cesapp-lib/core" + "os" + ctrl "sigs.k8s.io/controller-runtime" +) + +const ( + StageDevelopment = "development" + StageProduction = "production" + StageEnvironmentVariable = "STAGE" +) + +const cacheDir = "/tmp/dogu-registry-cache" + +var Stage = StageProduction + +var ( + envVarNamespace = "NAMESPACE" + log = ctrl.Log.WithName("config") +) + +// OperatorConfig contains all configurable values for the dogu operator. +type OperatorConfig struct { + // Namespace specifies the namespace that the operator is deployed to. + Namespace string `json:"namespace"` + // Version contains the current version of the operator + Version *core.Version `json:"version"` +} + +// NewOperatorConfig creates a new operator config by reading values from the environment variables +func NewOperatorConfig(version string) (*OperatorConfig, error) { + stage, err := getEnvVar(StageEnvironmentVariable) + if err != nil { + log.Error(err, "Error reading stage environment variable. Use Stage production") + } + Stage = stage + + if Stage == StageDevelopment { + log.Info("Starting in development mode! This is not recommended for production!") + } + + parsedVersion, err := core.ParseVersion(version) + if err != nil { + return nil, fmt.Errorf("failed to parse version: %w", err) + } + log.Info(fmt.Sprintf("Version: [%s]", version)) + + namespace, err := readNamespace() + if err != nil { + return nil, fmt.Errorf("failed to read namespace: %w", err) + } + log.Info(fmt.Sprintf("Deploying the k8s dogu operator in namespace %s", namespace)) + + return &OperatorConfig{ + Namespace: namespace, + Version: &parsedVersion, + }, nil +} + +func readNamespace() (string, error) { + namespace, err := getEnvVar(envVarNamespace) + if err != nil { + return "", fmt.Errorf("failed to get env var [%s]: %w", envVarNamespace, err) + } + + return namespace, nil +} + +func getEnvVar(name string) (string, error) { + ns, found := os.LookupEnv(name) + if !found { + return "", fmt.Errorf("environment variable %s must be set", name) + } + return ns, nil +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 0000000..84369c4 --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,36 @@ +package config + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewOperatorConfig(t *testing.T) { + _ = os.Unsetenv("NAMESPACE") + + expectedNamespace := "myNamespace" + + t.Run("Error on missing namespace env var", func(t *testing.T) { + // when + operatorConfig, err := NewOperatorConfig("0.0.0") + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "failed to get env var [NAMESPACE]: environment variable NAMESPACE must be set") + assert.Nil(t, operatorConfig) + }) + t.Setenv("NAMESPACE", expectedNamespace) + t.Run("Create config successfully", func(t *testing.T) { + // when + operatorConfig, err := NewOperatorConfig("0.1.0") + + // then + require.NoError(t, err) + require.NotNil(t, operatorConfig) + assert.Equal(t, expectedNamespace, operatorConfig.Namespace) + assert.Equal(t, "0.1.0", operatorConfig.Version.Raw) + }) +} diff --git a/pkg/controllers/backupController.go b/pkg/controllers/backupController.go new file mode 100644 index 0000000..8bb2fab --- /dev/null +++ b/pkg/controllers/backupController.go @@ -0,0 +1,40 @@ +package controllers + +import ( + "context" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/record" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +// backupReconciler watches every Service object in the cluster and creates ingress objects accordingly. +type backupReconciler struct { + client client.Client + recorder record.EventRecorder +} + +// NewBackupReconciler creates a new backup reconciler. +func NewBackupReconciler(client client.Client, recorder record.EventRecorder) *backupReconciler { + return &backupReconciler{ + client: client, + recorder: recorder, + } +} + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +func (r *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + logger.Info("Reconcile this backup manager") + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *backupReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&corev1.Service{}). + Complete(r) +} diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go new file mode 100644 index 0000000..db44a7c --- /dev/null +++ b/pkg/logging/logger.go @@ -0,0 +1,118 @@ +package logging + +import ( + "fmt" + "os" + "strings" + + "github.com/bombsimon/logrusr/v2" + "github.com/cloudogu/cesapp-lib/core" + "github.com/cloudogu/k8s-apply-lib/apply" + "github.com/go-logr/logr" + "github.com/sirupsen/logrus" + ctrl "sigs.k8s.io/controller-runtime" +) + +const logLevelEnvVar = "LOG_LEVEL" + +const ( + errorLevel int = iota + warningLevel + infoLevel + debugLevel +) + +var CurrentLogLevel = logrus.ErrorLevel + +type libraryLogger struct { + logger logr.LogSink + name string +} + +func (ll *libraryLogger) log(level int, args ...interface{}) { + ll.logger.Info(level, fmt.Sprintf("[%s] %s", ll.name, fmt.Sprint(args...))) +} + +func (ll *libraryLogger) logf(level int, format string, args ...interface{}) { + ll.logger.Info(level, fmt.Sprintf("[%s] %s", ll.name, fmt.Sprintf(format, args...))) +} + +func (ll *libraryLogger) Debug(args ...interface{}) { + ll.log(debugLevel, args...) +} + +func (ll *libraryLogger) Info(args ...interface{}) { + ll.log(infoLevel, args...) +} + +func (ll *libraryLogger) Warning(args ...interface{}) { + ll.log(warningLevel, args...) +} + +func (ll *libraryLogger) Error(args ...interface{}) { + ll.log(errorLevel, args...) +} + +func (ll *libraryLogger) Debugf(format string, args ...interface{}) { + ll.logf(debugLevel, format, args...) +} + +func (ll *libraryLogger) Infof(format string, args ...interface{}) { + ll.logf(infoLevel, format, args...) +} + +func (ll *libraryLogger) Warningf(format string, args ...interface{}) { + ll.logf(warningLevel, format, args...) +} + +func (ll *libraryLogger) Errorf(format string, args ...interface{}) { + ll.logf(errorLevel, format, args...) +} + +func getLogLevelFromEnv() (logrus.Level, error) { + logLevel, found := os.LookupEnv(logLevelEnvVar) + if !found || strings.TrimSpace(logLevel) == "" { + return logrus.ErrorLevel, nil + } + + level, err := logrus.ParseLevel(logLevel) + if err != nil { + return logrus.ErrorLevel, fmt.Errorf("value of log environment variable [%s] is not a valid log level: %w", logLevelEnvVar, err) + } + + return level, nil +} + +func ConfigureLogger() error { + level, err := getLogLevelFromEnv() + if err != nil { + return err + } + + // create logrus logger that can be styled and formatted + logrusLog := logrus.New() + logrusLog.SetFormatter(&logrus.TextFormatter{}) + logrusLog.SetLevel(level) + + CurrentLogLevel = level + + // convert logrus logger to logr logger + logrusLogrLogger := logrusr.New(logrusLog) + + // set logr logger as controller logger + ctrl.SetLogger(logrusLogrLogger) + + // set custom logger implementation to cesapp-lib logger + cesappLibLogger := libraryLogger{name: "cesapp-lib", logger: logrusLogrLogger.GetSink()} + core.GetLogger = func() core.Logger { + return &cesappLibLogger + } + + // set custom logger implementation to k8s-apply-lib logger + k8sApplyLibLogger := libraryLogger{name: "k8s-apply-lib", logger: logrusLogrLogger.GetSink()} + apply.GetLogger = func() apply.Logger { + return &k8sApplyLibLogger + } + + return nil +} diff --git a/pkg/logging/logger_test.go b/pkg/logging/logger_test.go new file mode 100644 index 0000000..03d154d --- /dev/null +++ b/pkg/logging/logger_test.go @@ -0,0 +1,179 @@ +package logging + +import ( + "github.com/cloudogu/k8s-backup-operator/pkg/mocks/external" + "os" + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + ctrl "sigs.k8s.io/controller-runtime" + + "github.com/cloudogu/cesapp-lib/core" +) + +func TestConfigureLogger(t *testing.T) { + originalControllerLogger := ctrl.Log + originalLibraryLogger := core.GetLogger() + defer func() { + ctrl.Log = originalControllerLogger + core.GetLogger = func() core.Logger { + return originalLibraryLogger + } + }() + + t.Run("create logger with no log level set in env -> should use default", func(t *testing.T) { + // given + _ = os.Unsetenv(logLevelEnvVar) + + // when + err := ConfigureLogger() + + // then + assert.NoError(t, err) + }) + t.Run("should not fail with empty string log level and return error level", func(t *testing.T) { + // given + t.Setenv(logLevelEnvVar, "") + + // when + err := ConfigureLogger() + + // then + assert.NoError(t, err) + assert.Equal(t, logrus.ErrorLevel, CurrentLogLevel) + }) + + t.Run("create logger with log level INFO", func(t *testing.T) { + // given + _ = os.Setenv(logLevelEnvVar, "INFO") + + // when + err := ConfigureLogger() + + // then + core.GetLogger().Info("test") + assert.NoError(t, err) + }) + + t.Run("create logger with invalid log level TEST_LEVEL", func(t *testing.T) { + // given + _ = os.Setenv(logLevelEnvVar, "TEST_LEVEL") + + // when + err := ConfigureLogger() + + // then + assert.Error(t, err) + assert.ErrorContains(t, err, "value of log environment variable [LOG_LEVEL] is not a valid log level") + }) +} + +func Test_libraryLogger_Debug(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", debugLevel, "[testLogger] test debug call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + logger.Debug("test debug call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Debugf(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", debugLevel, "[testLogger] myText - test debug call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + text := "myText" + logger.Debugf("%s - %s", text, "test debug call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Error(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", errorLevel, "[testLogger] test error call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + logger.Error("test error call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Errorf(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", errorLevel, "[testLogger] myText - test error call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + text := "myText" + logger.Errorf("%s - %s", text, "test error call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Info(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", infoLevel, "[testLogger] test info call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + logger.Info("test info call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Infof(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", infoLevel, "[testLogger] myText - test info call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + text := "myText" + logger.Infof("%s - %s", text, "test info call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Warning(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", warningLevel, "[testLogger] test warning call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + logger.Warning("test warning call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} + +func Test_libraryLogger_Warningf(t *testing.T) { + // given + loggerSink := &external.LogSink{} + loggerSink.On("Info", warningLevel, "[testLogger] myText - test warning call") + logger := libraryLogger{name: "testLogger", logger: loggerSink} + + // when + text := "myText" + logger.Warningf("%s - %s", text, "test warning call") + + // then + mock.AssertExpectationsForObjects(t, loggerSink) +} diff --git a/pkg/mocks/external/Client.go b/pkg/mocks/external/Client.go new file mode 100644 index 0000000..15506f8 --- /dev/null +++ b/pkg/mocks/external/Client.go @@ -0,0 +1,225 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package external + +import ( + context "context" + + client "sigs.k8s.io/controller-runtime/pkg/client" + + meta "k8s.io/apimachinery/pkg/api/meta" + + mock "github.com/stretchr/testify/mock" + + runtime "k8s.io/apimachinery/pkg/runtime" + + types "k8s.io/apimachinery/pkg/types" +) + +// Client is an autogenerated mock type for the Client type +type Client struct { + mock.Mock +} + +// Create provides a mock function with given fields: ctx, obj, opts +func (_m *Client) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.CreateOption) error); ok { + r0 = rf(ctx, obj, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Delete provides a mock function with given fields: ctx, obj, opts +func (_m *Client) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteOption) error); ok { + r0 = rf(ctx, obj, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteAllOf provides a mock function with given fields: ctx, obj, opts +func (_m *Client) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteAllOfOption) error); ok { + r0 = rf(ctx, obj, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Get provides a mock function with given fields: ctx, key, obj +func (_m *Client) Get(ctx context.Context, key types.NamespacedName, obj client.Object) error { + ret := _m.Called(ctx, key, obj) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.NamespacedName, client.Object) error); ok { + r0 = rf(ctx, key, obj) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// List provides a mock function with given fields: ctx, list, opts +func (_m *Client) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, list) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.ObjectList, ...client.ListOption) error); ok { + r0 = rf(ctx, list, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Patch provides a mock function with given fields: ctx, obj, patch, opts +func (_m *Client) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj, patch) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, client.Patch, ...client.PatchOption) error); ok { + r0 = rf(ctx, obj, patch, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// RESTMapper provides a mock function with given fields: +func (_m *Client) RESTMapper() meta.RESTMapper { + ret := _m.Called() + + var r0 meta.RESTMapper + if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(meta.RESTMapper) + } + } + + return r0 +} + +// Scheme provides a mock function with given fields: +func (_m *Client) Scheme() *runtime.Scheme { + ret := _m.Called() + + var r0 *runtime.Scheme + if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.Scheme) + } + } + + return r0 +} + +// Status provides a mock function with given fields: +func (_m *Client) Status() client.StatusWriter { + ret := _m.Called() + + var r0 client.StatusWriter + if rf, ok := ret.Get(0).(func() client.StatusWriter); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.StatusWriter) + } + } + + return r0 +} + +// Update provides a mock function with given fields: ctx, obj, opts +func (_m *Client) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.UpdateOption) error); ok { + r0 = rf(ctx, obj, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewClient interface { + mock.TestingT + Cleanup(func()) +} + +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewClient(t mockConstructorTestingTNewClient) *Client { + mock := &Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/mocks/external/EventRecorder.go b/pkg/mocks/external/EventRecorder.go new file mode 100644 index 0000000..dfdab1c --- /dev/null +++ b/pkg/mocks/external/EventRecorder.go @@ -0,0 +1,50 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package external + +import ( + mock "github.com/stretchr/testify/mock" + + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// EventRecorder is an autogenerated mock type for the EventRecorder type +type EventRecorder struct { + mock.Mock +} + +// AnnotatedEventf provides a mock function with given fields: object, annotations, eventtype, reason, messageFmt, args +func (_m *EventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, annotations, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Event provides a mock function with given fields: object, eventtype, reason, message +func (_m *EventRecorder) Event(object runtime.Object, eventtype string, reason string, message string) { + _m.Called(object, eventtype, reason, message) +} + +// Eventf provides a mock function with given fields: object, eventtype, reason, messageFmt, args +func (_m *EventRecorder) Eventf(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +type mockConstructorTestingTNewEventRecorder interface { + mock.TestingT + Cleanup(func()) +} + +// NewEventRecorder creates a new instance of EventRecorder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewEventRecorder(t mockConstructorTestingTNewEventRecorder) *EventRecorder { + mock := &EventRecorder{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/mocks/external/LogSink.go b/pkg/mocks/external/LogSink.go new file mode 100644 index 0000000..a2dd1cd --- /dev/null +++ b/pkg/mocks/external/LogSink.go @@ -0,0 +1,97 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package external + +import ( + logr "github.com/go-logr/logr" + mock "github.com/stretchr/testify/mock" +) + +// LogSink is an autogenerated mock type for the LogSink type +type LogSink struct { + mock.Mock +} + +// Enabled provides a mock function with given fields: level +func (_m *LogSink) Enabled(level int) bool { + ret := _m.Called(level) + + var r0 bool + if rf, ok := ret.Get(0).(func(int) bool); ok { + r0 = rf(level) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// Error provides a mock function with given fields: err, msg, keysAndValues +func (_m *LogSink) Error(err error, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, err, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// Info provides a mock function with given fields: level, msg, keysAndValues +func (_m *LogSink) Info(level int, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, level, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// Init provides a mock function with given fields: info +func (_m *LogSink) Init(info logr.RuntimeInfo) { + _m.Called(info) +} + +// WithName provides a mock function with given fields: name +func (_m *LogSink) WithName(name string) logr.LogSink { + ret := _m.Called(name) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(string) logr.LogSink); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +// WithValues provides a mock function with given fields: keysAndValues +func (_m *LogSink) WithValues(keysAndValues ...interface{}) logr.LogSink { + var _ca []interface{} + _ca = append(_ca, keysAndValues...) + ret := _m.Called(_ca...) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(...interface{}) logr.LogSink); ok { + r0 = rf(keysAndValues...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +type mockConstructorTestingTNewLogSink interface { + mock.TestingT + Cleanup(func()) +} + +// NewLogSink creates a new instance of LogSink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewLogSink(t mockConstructorTestingTNewLogSink) *LogSink { + mock := &LogSink{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/mocks/external/Manager.go b/pkg/mocks/external/Manager.go new file mode 100644 index 0000000..5606ea5 --- /dev/null +++ b/pkg/mocks/external/Manager.go @@ -0,0 +1,324 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package external + +import ( + cache "sigs.k8s.io/controller-runtime/pkg/cache" + client "sigs.k8s.io/controller-runtime/pkg/client" + + context "context" + + healthz "sigs.k8s.io/controller-runtime/pkg/healthz" + + http "net/http" + + logr "github.com/go-logr/logr" + + manager "sigs.k8s.io/controller-runtime/pkg/manager" + + meta "k8s.io/apimachinery/pkg/api/meta" + + mock "github.com/stretchr/testify/mock" + + record "k8s.io/client-go/tools/record" + + rest "k8s.io/client-go/rest" + + runtime "k8s.io/apimachinery/pkg/runtime" + + v1alpha1 "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" + + webhook "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// Manager is an autogenerated mock type for the Manager type +type Manager struct { + mock.Mock +} + +// Add provides a mock function with given fields: _a0 +func (_m *Manager) Add(_a0 manager.Runnable) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(manager.Runnable) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// AddHealthzCheck provides a mock function with given fields: name, check +func (_m *Manager) AddHealthzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// AddMetricsExtraHandler provides a mock function with given fields: path, handler +func (_m *Manager) AddMetricsExtraHandler(path string, handler http.Handler) error { + ret := _m.Called(path, handler) + + var r0 error + if rf, ok := ret.Get(0).(func(string, http.Handler) error); ok { + r0 = rf(path, handler) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// AddReadyzCheck provides a mock function with given fields: name, check +func (_m *Manager) AddReadyzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Elected provides a mock function with given fields: +func (_m *Manager) Elected() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// GetAPIReader provides a mock function with given fields: +func (_m *Manager) GetAPIReader() client.Reader { + ret := _m.Called() + + var r0 client.Reader + if rf, ok := ret.Get(0).(func() client.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Reader) + } + } + + return r0 +} + +// GetCache provides a mock function with given fields: +func (_m *Manager) GetCache() cache.Cache { + ret := _m.Called() + + var r0 cache.Cache + if rf, ok := ret.Get(0).(func() cache.Cache); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.Cache) + } + } + + return r0 +} + +// GetClient provides a mock function with given fields: +func (_m *Manager) GetClient() client.Client { + ret := _m.Called() + + var r0 client.Client + if rf, ok := ret.Get(0).(func() client.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Client) + } + } + + return r0 +} + +// GetConfig provides a mock function with given fields: +func (_m *Manager) GetConfig() *rest.Config { + ret := _m.Called() + + var r0 *rest.Config + if rf, ok := ret.Get(0).(func() *rest.Config); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Config) + } + } + + return r0 +} + +// GetControllerOptions provides a mock function with given fields: +func (_m *Manager) GetControllerOptions() v1alpha1.ControllerConfigurationSpec { + ret := _m.Called() + + var r0 v1alpha1.ControllerConfigurationSpec + if rf, ok := ret.Get(0).(func() v1alpha1.ControllerConfigurationSpec); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(v1alpha1.ControllerConfigurationSpec) + } + + return r0 +} + +// GetEventRecorderFor provides a mock function with given fields: name +func (_m *Manager) GetEventRecorderFor(name string) record.EventRecorder { + ret := _m.Called(name) + + var r0 record.EventRecorder + if rf, ok := ret.Get(0).(func(string) record.EventRecorder); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(record.EventRecorder) + } + } + + return r0 +} + +// GetFieldIndexer provides a mock function with given fields: +func (_m *Manager) GetFieldIndexer() client.FieldIndexer { + ret := _m.Called() + + var r0 client.FieldIndexer + if rf, ok := ret.Get(0).(func() client.FieldIndexer); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.FieldIndexer) + } + } + + return r0 +} + +// GetLogger provides a mock function with given fields: +func (_m *Manager) GetLogger() logr.Logger { + ret := _m.Called() + + var r0 logr.Logger + if rf, ok := ret.Get(0).(func() logr.Logger); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(logr.Logger) + } + + return r0 +} + +// GetRESTMapper provides a mock function with given fields: +func (_m *Manager) GetRESTMapper() meta.RESTMapper { + ret := _m.Called() + + var r0 meta.RESTMapper + if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(meta.RESTMapper) + } + } + + return r0 +} + +// GetScheme provides a mock function with given fields: +func (_m *Manager) GetScheme() *runtime.Scheme { + ret := _m.Called() + + var r0 *runtime.Scheme + if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.Scheme) + } + } + + return r0 +} + +// GetWebhookServer provides a mock function with given fields: +func (_m *Manager) GetWebhookServer() *webhook.Server { + ret := _m.Called() + + var r0 *webhook.Server + if rf, ok := ret.Get(0).(func() *webhook.Server); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*webhook.Server) + } + } + + return r0 +} + +// SetFields provides a mock function with given fields: _a0 +func (_m *Manager) SetFields(_a0 interface{}) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(interface{}) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Start provides a mock function with given fields: ctx +func (_m *Manager) Start(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewManager interface { + mock.TestingT + Cleanup(func()) +} + +// NewManager creates a new instance of Manager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewManager(t mockConstructorTestingTNewManager) *Manager { + mock := &Manager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/mocks/external/StatusWriter.go b/pkg/mocks/external/StatusWriter.go new file mode 100644 index 0000000..afaf43d --- /dev/null +++ b/pkg/mocks/external/StatusWriter.go @@ -0,0 +1,73 @@ +// Code generated by mockery v2.14.0. DO NOT EDIT. + +package external + +import ( + context "context" + + client "sigs.k8s.io/controller-runtime/pkg/client" + + mock "github.com/stretchr/testify/mock" +) + +// StatusWriter is an autogenerated mock type for the StatusWriter type +type StatusWriter struct { + mock.Mock +} + +// Patch provides a mock function with given fields: ctx, obj, patch, opts +func (_m *StatusWriter) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj, patch) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, client.Patch, ...client.PatchOption) error); ok { + r0 = rf(ctx, obj, patch, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Update provides a mock function with given fields: ctx, obj, opts +func (_m *StatusWriter) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, obj) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.UpdateOption) error); ok { + r0 = rf(ctx, obj, opts...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewStatusWriter interface { + mock.TestingT + Cleanup(func()) +} + +// NewStatusWriter creates a new instance of StatusWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewStatusWriter(t mockConstructorTestingTNewStatusWriter) *StatusWriter { + mock := &StatusWriter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/mocks/external/external.go b/pkg/mocks/external/external.go new file mode 100644 index 0000000..e435ddf --- /dev/null +++ b/pkg/mocks/external/external.go @@ -0,0 +1,3 @@ +// Package external implements mocks that implement 3rd party interfaces, t. i. interfaces which we do not control. +// In order to avoid package dependency cycles these mock implementations reside in this package. +package external diff --git a/release_args.sh b/release_args.sh new file mode 100644 index 0000000..206e777 --- /dev/null +++ b/release_args.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -o errexit +set -o nounset +set -o pipefail + +# this function will be sourced from release.sh and be called from release_functions.sh +update_versions_modify_files() { + newReleaseVersion="${1}" + kustomizationYAML=config/manager/kustomization.yaml + + yq "with(.images[] | select(.name == \"controller\") ; .newTag = \"${newReleaseVersion}\")" "${kustomizationYAML}" \ + > tmpfile \ + && mv tmpfile "${kustomizationYAML}" +} + +update_versions_stage_modified_files() { + kustomizationYAML=config/manager/kustomization.yaml + + git add "${kustomizationYAML}" +} diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..72267e2 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,14 @@ +sonar.projectKey=k8s-backup-operator +sonar.projectName=k8s-backup-operator +sonar.projectVersion=0.0.0-dev + +sonar.go.coverage.reportPaths=target/unit-test/coverage.out,target/k8s-integration-test/report-k8s-integration.out +sonar.go.golangci-lint.reportPaths=target/static-analysis/static-analysis-cs.log + +sonar.sources=. + +sonar.exclusions=**/mocks/**,**/zz_generated.deepcopy.go,**/*Mock.go + +sonar.tests=. +sonar.test.inclusions=**/*_test.go +sonar.test.exclusions=**/vendor/**,**/mocks/**,**/zz_generated.deepcopy.go,**/*Mock.go \ No newline at end of file From 8aa29794578d9cafae129d81b511b82e314d95aa Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Wed, 30 Aug 2023 17:01:42 +0200 Subject: [PATCH 02/37] #1 Initialize backup-operator This commit contains new Backup and Restore CRDs generated with kubebuilder v4. Makefiles have been updated as well. A ClientSet for managing Backup, Restore as well as the default Kubernetes resources has been written as well. Useless copy-paste artifacts have been deleted. --- .mockery.yaml | 4 + Dockerfile | 6 +- Jenkinsfile | 2 +- Makefile | 38 +- PROJECT | 19 +- build/make/k8s-controller.mk | 4 +- build/make/k8s-dogu.mk | 4 +- build/make/k8s.mk | 79 +- build/make/mockery.yaml | 4 + build/make/mocks.mk | 27 + build/make/variables.mk | 6 +- build/make/version-sha.mk | 18 + .../crd/bases/k8s.cloudogu.com_backups.yaml | 49 + .../crd/bases/k8s.cloudogu.com_restores.yaml | 49 + config/crd/kustomization.yaml | 24 + config/crd/kustomizeconfig.yaml | 19 + .../crd/patches/cainjection_in_backups.yaml | 7 + .../crd/patches/cainjection_in_restores.yaml | 7 + config/crd/patches/webhook_in_backups.yaml | 16 + config/crd/patches/webhook_in_restores.yaml | 16 + config/default/kustomization.yaml | 153 +- config/default/manager_auth_proxy_patch.yaml | 8 +- config/default/manager_config_patch.yaml | 10 - config/labels/crd_label_patch.yaml | 7 + config/labels/kustomization.yaml | 10 + config/manager/controller_manager_config.yaml | 11 - config/manager/kustomization.yaml | 12 - config/manager/manager.yaml | 94 +- config/prometheus/monitor.yaml | 6 + .../rbac/auth_proxy_client_clusterrole.yaml | 15 +- config/rbac/auth_proxy_role.yaml | 9 +- config/rbac/auth_proxy_role_binding.yaml | 12 +- config/rbac/auth_proxy_service.yaml | 7 + config/rbac/backup_editor_role.yaml | 31 + config/rbac/backup_viewer_role.yaml | 27 + config/rbac/cluster_role.yaml | 16 - config/rbac/cluster_role_binding.yaml | 15 - config/rbac/dogu_editor_role.yaml | 24 - config/rbac/dogu_viewer_role.yaml | 20 - config/rbac/kustomization.yaml | 2 - config/rbac/leader_election_role.yaml | 7 + config/rbac/leader_election_role_binding.yaml | 8 + config/rbac/restore_editor_role.yaml | 31 + config/rbac/restore_viewer_role.yaml | 27 + config/rbac/role.yaml | 54 +- config/rbac/role_binding.yaml | 12 +- config/rbac/service_account.yaml | 8 + config/samples/cas_config.sh | 10 - .../hallowelt/bluespice-pdfrenderer.yaml | 12 - config/samples/hallowelt/bluespice.yaml | 12 - config/samples/hallowelt/drawio.yaml | 12 - config/samples/itz-bund/teamscale.yaml | 12 - config/samples/k8s/nginx-ingress.yaml | 12 - config/samples/k8s/nginx-static.yaml | 12 - config/samples/k8s_v1_backup.yaml | 12 + config/samples/k8s_v1_dogu.yaml | 8 - config/samples/k8s_v1_restore.yaml | 12 + config/samples/kustomization.yaml | 5 + config/samples/ldap-mapper.sh | 3 - config/samples/ldap_config.sh | 2 - config/samples/official/backup.yaml | 12 - config/samples/official/cas.yaml | 12 - config/samples/official/cas_config.sh | 10 - config/samples/official/cockpit.yaml | 12 - config/samples/official/elasticsearch.yaml | 12 - config/samples/official/gotenberg.yaml | 12 - config/samples/official/jenkins.yaml | 12 - config/samples/official/ldap-mapper.sh | 3 - config/samples/official/ldap-mapper.yaml | 12 - config/samples/official/ldap.yaml | 12 - config/samples/official/ldap_config.sh | 2 - config/samples/official/mysql.yaml | 12 - config/samples/official/nexus.yaml | 12 - config/samples/official/plantuml.yaml | 12 - config/samples/official/postfix.yaml | 14 - config/samples/official/postfix_config.sh | 1 - config/samples/official/postgresql.yaml | 14 - config/samples/official/redis.yaml | 12 - config/samples/official/redmine.yaml | 12 - config/samples/official/scm.yaml | 13 - config/samples/official/smeagol.yaml | 12 - config/samples/official/sonar.yaml | 12 - config/samples/official/swaggerui.yaml | 12 - config/samples/official/usermgt.yaml | 14 - config/samples/postfix_config.sh | 1 - config/samples/premium/admin.yaml | 12 - config/samples/premium/confluence.yaml | 12 - config/samples/premium/jira.yaml | 12 - go.mod | 119 +- go.sum | 1619 ++--------------- main.go | 134 +- main_internal_test.go | 165 -- pkg/api/ecosystem/backupRestClient.go | 251 +++ pkg/api/ecosystem/ecosystemClientSet.go | 94 + pkg/api/ecosystem/restoreRestClient.go | 251 +++ pkg/api/v1/backup_types.go | 53 + pkg/api/v1/groupversion_info.go | 20 + pkg/api/v1/restore_types.go | 53 + pkg/api/v1/zz_generated.deepcopy.go | 192 ++ pkg/config/config.go | 65 +- pkg/config/config_test.go | 36 - pkg/controllers/backupController.go | 40 - pkg/controllers/backupReconciler.go | 49 + pkg/controllers/interfaces.go | 15 + pkg/controllers/restoreReconciler.go | 48 + pkg/controllers/suite_int_test.go | 64 + pkg/logging/logger.go | 118 -- pkg/logging/logger_test.go | 179 -- pkg/mocks/external/Client.go | 225 --- pkg/mocks/external/EventRecorder.go | 50 - pkg/mocks/external/LogSink.go | 97 - pkg/mocks/external/Manager.go | 324 ---- pkg/mocks/external/StatusWriter.go | 73 - pkg/mocks/external/external.go | 3 - pkg/retry/retry.go | 18 + 115 files changed, 2237 insertions(+), 3576 deletions(-) create mode 100644 .mockery.yaml create mode 100644 build/make/mockery.yaml create mode 100644 build/make/mocks.mk create mode 100644 build/make/version-sha.mk create mode 100644 config/crd/bases/k8s.cloudogu.com_backups.yaml create mode 100644 config/crd/bases/k8s.cloudogu.com_restores.yaml create mode 100644 config/crd/kustomization.yaml create mode 100644 config/crd/kustomizeconfig.yaml create mode 100644 config/crd/patches/cainjection_in_backups.yaml create mode 100644 config/crd/patches/cainjection_in_restores.yaml create mode 100644 config/crd/patches/webhook_in_backups.yaml create mode 100644 config/crd/patches/webhook_in_restores.yaml create mode 100644 config/labels/crd_label_patch.yaml create mode 100644 config/labels/kustomization.yaml delete mode 100644 config/manager/controller_manager_config.yaml create mode 100644 config/rbac/backup_editor_role.yaml create mode 100644 config/rbac/backup_viewer_role.yaml delete mode 100644 config/rbac/cluster_role.yaml delete mode 100644 config/rbac/cluster_role_binding.yaml delete mode 100644 config/rbac/dogu_editor_role.yaml delete mode 100644 config/rbac/dogu_viewer_role.yaml create mode 100644 config/rbac/restore_editor_role.yaml create mode 100644 config/rbac/restore_viewer_role.yaml delete mode 100644 config/samples/cas_config.sh delete mode 100644 config/samples/hallowelt/bluespice-pdfrenderer.yaml delete mode 100644 config/samples/hallowelt/bluespice.yaml delete mode 100644 config/samples/hallowelt/drawio.yaml delete mode 100644 config/samples/itz-bund/teamscale.yaml delete mode 100644 config/samples/k8s/nginx-ingress.yaml delete mode 100644 config/samples/k8s/nginx-static.yaml create mode 100644 config/samples/k8s_v1_backup.yaml delete mode 100644 config/samples/k8s_v1_dogu.yaml create mode 100644 config/samples/k8s_v1_restore.yaml create mode 100644 config/samples/kustomization.yaml delete mode 100644 config/samples/ldap-mapper.sh delete mode 100644 config/samples/ldap_config.sh delete mode 100644 config/samples/official/backup.yaml delete mode 100644 config/samples/official/cas.yaml delete mode 100755 config/samples/official/cas_config.sh delete mode 100644 config/samples/official/cockpit.yaml delete mode 100644 config/samples/official/elasticsearch.yaml delete mode 100644 config/samples/official/gotenberg.yaml delete mode 100644 config/samples/official/jenkins.yaml delete mode 100755 config/samples/official/ldap-mapper.sh delete mode 100644 config/samples/official/ldap-mapper.yaml delete mode 100644 config/samples/official/ldap.yaml delete mode 100755 config/samples/official/ldap_config.sh delete mode 100644 config/samples/official/mysql.yaml delete mode 100644 config/samples/official/nexus.yaml delete mode 100644 config/samples/official/plantuml.yaml delete mode 100644 config/samples/official/postfix.yaml delete mode 100755 config/samples/official/postfix_config.sh delete mode 100644 config/samples/official/postgresql.yaml delete mode 100644 config/samples/official/redis.yaml delete mode 100644 config/samples/official/redmine.yaml delete mode 100644 config/samples/official/scm.yaml delete mode 100644 config/samples/official/smeagol.yaml delete mode 100644 config/samples/official/sonar.yaml delete mode 100644 config/samples/official/swaggerui.yaml delete mode 100644 config/samples/official/usermgt.yaml delete mode 100644 config/samples/postfix_config.sh delete mode 100644 config/samples/premium/admin.yaml delete mode 100644 config/samples/premium/confluence.yaml delete mode 100644 config/samples/premium/jira.yaml delete mode 100644 main_internal_test.go create mode 100644 pkg/api/ecosystem/backupRestClient.go create mode 100644 pkg/api/ecosystem/ecosystemClientSet.go create mode 100644 pkg/api/ecosystem/restoreRestClient.go create mode 100644 pkg/api/v1/backup_types.go create mode 100644 pkg/api/v1/groupversion_info.go create mode 100644 pkg/api/v1/restore_types.go create mode 100644 pkg/api/v1/zz_generated.deepcopy.go delete mode 100644 pkg/config/config_test.go delete mode 100644 pkg/controllers/backupController.go create mode 100644 pkg/controllers/backupReconciler.go create mode 100644 pkg/controllers/interfaces.go create mode 100644 pkg/controllers/restoreReconciler.go create mode 100644 pkg/controllers/suite_int_test.go delete mode 100644 pkg/logging/logger.go delete mode 100644 pkg/logging/logger_test.go delete mode 100644 pkg/mocks/external/Client.go delete mode 100644 pkg/mocks/external/EventRecorder.go delete mode 100644 pkg/mocks/external/LogSink.go delete mode 100644 pkg/mocks/external/Manager.go delete mode 100644 pkg/mocks/external/StatusWriter.go delete mode 100644 pkg/mocks/external/external.go create mode 100644 pkg/retry/retry.go diff --git a/.mockery.yaml b/.mockery.yaml new file mode 100644 index 0000000..67b4339 --- /dev/null +++ b/.mockery.yaml @@ -0,0 +1,4 @@ +inpackage: True +testonly: True +with-expecter: True +keeptree: False \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index adc0125..d614eee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,5 @@ # Build the manager binary -FROM golang:1.18 as builder - -ENV GOPRIVATE=github.com/cloudogu/cesapp/v5 +FROM golang:1.21 AS builder WORKDIR /workspace @@ -35,7 +33,7 @@ RUN make compile-generic FROM gcr.io/distroless/static:nonroot LABEL maintainer="hello@cloudogu.com" \ NAME="k8s-backup-operator" \ - VERSION="0.19.0" + VERSION="0.1.0" WORKDIR / COPY --from=builder /workspace/target/k8s-backup-operator . diff --git a/Jenkinsfile b/Jenkinsfile index e40f5b9..f3a0aa5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,7 +13,7 @@ github = new GitHub(this, git) changelog = new Changelog(this) Docker docker = new Docker(this) gpg = new Gpg(this, docker) -goVersion = "1.18" +goVersion = "1.21" // Configuration of repository repositoryOwner = "cloudogu" diff --git a/Makefile b/Makefile index 2c852e1..880f7d2 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ # Set these to the desired values ARTIFACT_ID=k8s-backup-operator -VERSION=0.19.0 +VERSION=0.1.0 ## Image URL to use all building/pushing image targets IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} -GOTAG?=1.18 -MAKEFILES_VERSION=7.0.1 -LINT_VERSION=v1.45.2 +GOTAG?=1.21 +MAKEFILES_VERSION=7.10.0 +LINT_VERSION=v1.52.1 STAGE?=production ADDITIONAL_CLEAN=dist-clean @@ -20,6 +20,7 @@ include build/make/test-unit.mk include build/make/static-analysis.mk include build/make/clean.mk include build/make/digital-signature.mk +include build/make/mocks.mk PRE_COMPILE=generate K8S_PRE_GENERATE_TARGETS=k8s-create-temporary-resource template-dev-only-image-pull-policy @@ -34,7 +35,9 @@ build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. @echo "Generate manifests..." - @$(CONTROLLER_GEN) rbac:roleName=manager-role webhook paths="./..." + @$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases + @make template-crd-labels + @cp config/crd/bases/k8s.cloudogu.com_dogus.yaml api/v1/ .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. @@ -43,6 +46,19 @@ generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and ##@ Deployment +.PHONY: install +install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl apply -f - + +.PHONY: uninstall +uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. + @$(KUSTOMIZE) build config/crd | kubectl delete --wait=false --ignore-not-found=true -f - + @kubectl patch crd/backups.k8s.cloudogu.com -p '{"metadata":{"finalizers":[]}}' --type=merge || true + +.PHONY: template-crd-labels +template-crd-labels: kustomize + @$(KUSTOMIZE) build config/labels -o config/crd/bases/k8s.cloudogu.com_dogus.yaml + .PHONY: template-stage template-stage: @echo "Setting STAGE env in deployment to ${STAGE}!" @@ -69,15 +85,3 @@ kill-operator-pod: print-debug-info: ## Generates indo and the list of environment variables required to start the operator in debug mode. @echo "The target generates a list of env variables required to start the operator in debug mode. These can be pasted directly into the 'go build' run configuration in IntelliJ to run and debug the operator on-demand." @echo "STAGE=$(STAGE);LOG_LEVEL=$(LOG_LEVEL);KUBECONFIG=$(KUBECONFIG);NAMESPACE=$(NAMESPACE);DOGU_REGISTRY_ENDPOINT=$(DOGU_REGISTRY_ENDPOINT);DOGU_REGISTRY_USERNAME=$(DOGU_REGISTRY_USERNAME);DOGU_REGISTRY_PASSWORD=$(DOGU_REGISTRY_PASSWORD);DOCKER_REGISTRY={\"auths\":{\"$(docker_registry_server)\":{\"username\":\"$(docker_registry_username)\",\"password\":\"$(docker_registry_password)\",\"email\":\"ignore@me.com\",\"auth\":\"ignoreMe\"}}}" - -##@ Mockery - -MOCKERY_BIN=${UTILITY_BIN_PATH}/mockery -MOCKERY_VERSION=v2.15.0 - -${MOCKERY_BIN}: ${UTILITY_BIN_PATH} - $(call go-get-tool,$(MOCKERY_BIN),github.com/vektra/mockery/v2@$(MOCKERY_VERSION)) - -mocks: ${MOCKERY_BIN} ## This target is used to generate all mocks for the dogu operator. - @cd $(WORKDIR)/controllers/internal && ${MOCKERY_BIN} --all - @echo "Mocks successfully created." \ No newline at end of file diff --git a/PROJECT b/PROJECT index d3d2119..aacdf47 100644 --- a/PROJECT +++ b/PROJECT @@ -1,6 +1,10 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: cloudogu.com layout: -- go.kubebuilder.io/v3 +- go.kubebuilder.io/v4 projectName: k8s-backup-operator repo: github.com/cloudogu/k8s-backup-operator resources: @@ -10,7 +14,16 @@ resources: controller: true domain: cloudogu.com group: k8s - kind: Dogu - path: github.com/cloudogu/k8s-backup-operator/api/v1 + kind: Restore + path: github.com/cloudogu/k8s-backup-operator/pkg/api/v1 + version: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: cloudogu.com + group: k8s + kind: Backup + path: github.com/cloudogu/k8s-backup-operator/pkg/api/v1 version: v1 version: "3" diff --git a/build/make/k8s-controller.mk b/build/make/k8s-controller.mk index feadb0c..5735f00 100644 --- a/build/make/k8s-controller.mk +++ b/build/make/k8s-controller.mk @@ -83,12 +83,12 @@ k8s-integration-test: $(K8S_INTEGRATION_TEST_DIR) manifests generate envtest ## CONTROLLER_GEN = $(UTILITY_BIN_PATH)/controller-gen .PHONY: controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.11.3) KUSTOMIZE = $(UTILITY_BIN_PATH)/kustomize .PHONY: kustomize kustomize: ## Download kustomize locally if necessary. - $(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.2) + $(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.7) ENVTEST = $(UTILITY_BIN_PATH)/setup-envtest .PHONY: envtest diff --git a/build/make/k8s-dogu.mk b/build/make/k8s-dogu.mk index 17a39d9..c498dcd 100644 --- a/build/make/k8s-dogu.mk +++ b/build/make/k8s-dogu.mk @@ -6,7 +6,7 @@ DOGU_JSON_DEV_FILE=${TARGET_DIR}/dogu.json ARTIFACT_ID=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|.*/||g") # Namespace of the dogu is extracted from the dogu.json ARTIFACT_NAMESPACE=$(shell $(BINARY_YQ) -e ".Name" $(DOGU_JSON_FILE) | sed "s|/.*||g") -# Namespace of the dogu is extracted from the dogu.json +# Version of the dogu is extracted from the dogu.json VERSION=$(shell $(BINARY_YQ) -e ".Version" $(DOGU_JSON_FILE)) # Image of the dogu is extracted from the dogu.json IMAGE=$(shell $(BINARY_YQ) -e ".Image" $(DOGU_JSON_FILE)):$(VERSION) @@ -40,5 +40,5 @@ K8S_RESOURCE_DOGU_CR_TEMPLATE_YAML ?= $(WORKDIR)/build/make/k8s-dogu.tpl install-dogu-descriptor: ${BINARY_YQ} $(TARGET_DIR) ## Installs a configmap with current dogu.json into the cluster. @echo "Generate configmap from dogu.json..." @$(BINARY_YQ) ".Image=\"${IMAGE_DEV_WITHOUT_TAG}\"" ${DOGU_JSON_FILE} > ${DOGU_JSON_DEV_FILE} - @kubectl create configmap "$(ARTIFACT_ID)-descriptor" --from-file=$(DOGU_JSON_DEV_FILE) --dry-run=client -o yaml | kubectl apply -f - + @kubectl create configmap "$(ARTIFACT_ID)-descriptor" --from-file=$(DOGU_JSON_DEV_FILE) --dry-run=client -o yaml | kubectl apply -f - --namespace=${NAMESPACE} @echo "Done." diff --git a/build/make/k8s.mk b/build/make/k8s.mk index a9233d0..c569fa3 100644 --- a/build/make/k8s.mk +++ b/build/make/k8s.mk @@ -7,9 +7,8 @@ endif ## Variables BINARY_YQ = $(UTILITY_BIN_PATH)/yq +BINARY_HELM = $(UTILITY_BIN_PATH)/helm -# The cluster root variable is used to the build images to the cluster. It can be defined in a .myenv file. -K8S_CLUSTER_ROOT ?= # The productive tag of the image IMAGE ?= @@ -21,18 +20,17 @@ K3CES_REGISTRY_URL_PREFIX="${K3S_CLUSTER_FQDN}:${K3S_LOCAL_REGISTRY_PORT}" # the current namespace and the dev image. K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR)/make/k8s K8S_RESOURCE_TEMP_YAML ?= $(K8S_RESOURCE_TEMP_FOLDER)/$(ARTIFACT_ID)_$(VERSION).yaml - -# The current namespace is extracted from the current context. -K8S_CURRENT_NAMESPACE=$(shell kubectl config view --minify -o jsonpath='{..namespace}') +K8S_HELM_TARGET ?= $(K8S_RESOURCE_TEMP_FOLDER)/helm +K8S_HELM_RESSOURCES ?= k8s/helm ##@ K8s - Variables .PHONY: check-all-vars -check-all-vars: check-k8s-cluster-root-env-var check-k8s-image-env-var check-k8s-artifact-id check-etc-hosts check-insecure-cluster-registry ## Conduct a sanity check against selected build artefacts or local environment +check-all-vars: check-k8s-image-env-var check-k8s-artifact-id check-etc-hosts check-insecure-cluster-registry check-k8s-namespace-env-var ## Conduct a sanity check against selected build artefacts or local environment -.PHONY: check-k8s-cluster-root-env-var -check-k8s-cluster-root-env-var: - @$(call check_defined, K8S_CLUSTER_ROOT, root path of your k3ces) +.PHONY: check-k8s-namespace-env-var +check-k8s-namespace-env-var: + @$(call check_defined, NAMESPACE, k8s namespace) .PHONY: check-k8s-image-env-var check-k8s-image-env-var: @@ -60,7 +58,7 @@ ${K8S_RESOURCE_TEMP_FOLDER}: .PHONY: k8s-delete k8s-delete: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Deletes all dogu related resources from the K8s cluster. @echo "Delete old dogu resources..." - @kubectl delete -f $(K8S_RESOURCE_TEMP_YAML) --wait=false --ignore-not-found=true + @kubectl delete -f $(K8S_RESOURCE_TEMP_YAML) --wait=false --ignore-not-found=true --namespace=${NAMESPACE} # The additional targets executed after the generate target, executed before each apply and delete. The generate target # produces a temporary yaml. This yaml is accessible via K8S_RESOURCE_TEMP_YAML an can be changed before the apply/delete. @@ -71,14 +69,64 @@ K8S_PRE_GENERATE_TARGETS ?= k8s-create-temporary-resource .PHONY: k8s-generate k8s-generate: ${BINARY_YQ} $(K8S_RESOURCE_TEMP_FOLDER) $(K8S_PRE_GENERATE_TARGETS) ## Generates the final resource yaml. @echo "Applying general transformations..." - @sed -i "s/'{{ .Namespace }}'/$(K8S_CURRENT_NAMESPACE)/" $(K8S_RESOURCE_TEMP_YAML) + @sed -i "s/'{{ .Namespace }}'/$(NAMESPACE)/" $(K8S_RESOURCE_TEMP_YAML) @$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").image)=\"$(IMAGE_DEV)\"" $(K8S_RESOURCE_TEMP_YAML) @echo "Done." .PHONY: k8s-apply k8s-apply: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Applies all generated K8s resources to the current cluster and namespace. @echo "Apply generated K8s resources..." - @kubectl apply -f $(K8S_RESOURCE_TEMP_YAML) + @kubectl apply -f $(K8S_RESOURCE_TEMP_YAML) --namespace=${NAMESPACE} + +##@ K8s - Helm general + +${K8S_HELM_RESSOURCES}/Chart.yaml: ${BINARY_HELM} ## Creates the Chart.yaml-template if missing + @echo "Create Chart.yaml..." + @mkdir -p ${K8S_HELM_RESSOURCES}/tmp/ + @${BINARY_HELM} create ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID} + @cp ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID}/Chart.yaml ${K8S_HELM_RESSOURCES}/ + @rm -dr ${K8S_HELM_RESSOURCES}/tmp + @sed -i 's/appVersion: ".*"/appVersion: "0.0.0-replaceme"/' ${K8S_HELM_RESSOURCES}/Chart.yaml + @sed -i 's/version: .*/version: 0.0.0-replaceme/' ${K8S_HELM_RESSOURCES}/Chart.yaml + +.PHONY: k8s-helm-delete +k8s-helm-delete: ${BINARY_HELM} ## Uninstalls the current helm chart. + @echo "Uninstall helm chart" + @${BINARY_HELM} uninstall ${ARTIFACT_ID} + +.PHONY: k8s-helm-generate-chart +k8s-helm-generate-chart: ${K8S_HELM_RESSOURCES}/Chart.yaml $(K8S_RESOURCE_TEMP_FOLDER) ## Generates the final helm chart. + @echo "Generate helm chart..." + @rm -drf ${K8S_HELM_TARGET} # delete folder, so Chart.yaml is newly created from template + @mkdir -p ${K8S_HELM_TARGET}/templates + @cp $(K8S_RESOURCE_TEMP_YAML) ${K8S_HELM_TARGET}/templates + @cp ${K8S_HELM_RESSOURCES}/Chart.yaml ${K8S_HELM_TARGET} + @sed -i 's/appVersion: "0.0.0-replaceme"/appVersion: "${VERSION}"/' ${K8S_HELM_TARGET}/Chart.yaml + @sed -i 's/version: 0.0.0-replaceme/version: ${VERSION}/' ${K8S_HELM_TARGET}/Chart.yaml + +##@ K8s - Helm dev targets + +.PHONY: k8s-helm-generate +k8s-helm-generate: k8s-generate k8s-helm-generate-chart ## Generates the final helm chart with dev-urls. + +.PHONY: k8s-helm-apply +k8s-helm-apply: ${BINARY_HELM} image-import k8s-helm-generate $(K8S_POST_GENERATE_TARGETS) ## Generates and installs the helm chart. + @echo "Apply generated helm chart" + @${BINARY_HELM} upgrade -i ${ARTIFACT_ID} ${K8S_HELM_TARGET} + +.PHONY: k8s-helm-reinstall +k8s-helm-reinstall: k8s-helm-delete k8s-helm-apply ## Uninstalls the current helm chart and reinstalls it. + +##@ K8s - Helm release targets + +.PHONY: k8s-helm-generate-release +k8s-helm-generate-release: $(K8S_PRE_GENERATE_TARGETS) k8s-helm-generate-chart ## Generates the final helm chart with release urls. + @sed -i "s/'{{ .Namespace }}'/'{{ .Release.Namespace }}'/" ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml + +.PHONY: k8s-helm-package-release +k8s-helm-package-release: ${BINARY_HELM} k8s-helm-generate-release $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. + @echo "Package generated helm chart" + @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} ##@ K8s - Docker @@ -120,5 +168,8 @@ __check_defined = \ $(if $(value $1),, \ $(error Undefined $1$(if $2, ($2)))) -${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download controller-gen locally if necessary. - $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) \ No newline at end of file +${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download yq locally if necessary. + $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) + +${BINARY_HELM}: $(UTILITY_BIN_PATH) ## Download helm locally if necessary. + $(call go-get-tool,$(BINARY_HELM),helm.sh/helm/v3/cmd/helm@latest) diff --git a/build/make/mockery.yaml b/build/make/mockery.yaml new file mode 100644 index 0000000..67b4339 --- /dev/null +++ b/build/make/mockery.yaml @@ -0,0 +1,4 @@ +inpackage: True +testonly: True +with-expecter: True +keeptree: False \ No newline at end of file diff --git a/build/make/mocks.mk b/build/make/mocks.mk new file mode 100644 index 0000000..9e61b46 --- /dev/null +++ b/build/make/mocks.mk @@ -0,0 +1,27 @@ +##@ Mocking + +MOCKERY_BIN=${UTILITY_BIN_PATH}/mockery +MOCKERY_VERSION=v2.20.0 +MOCKERY_YAML=${WORKDIR}/.mockery.yaml + +${MOCKERY_BIN}: ${UTILITY_BIN_PATH} + $(call go-get-tool,$(MOCKERY_BIN),github.com/vektra/mockery/v2@$(MOCKERY_VERSION)) + +${MOCKERY_YAML}: + @cp ${WORKDIR}/build/make/mockery.yaml ${WORKDIR}/.mockery.yaml + +.PHONY: mocks +mocks: ${MOCKERY_BIN} ${MOCKERY_YAML} ## This target is used to generate mocks for all interfaces in a project. + @for dir in ${WORKDIR}/*/ ;\ + do \ + # removes trailing '/' \ + dir=$${dir%*/} ;\ + # removes everything before the last '/' \ + dir=$${dir##*/} ;\ + if ! echo '${MOCKERY_IGNORED}' | egrep -q "\b$${dir}\b" ;\ + then \ + echo "Creating mocks for $${dir}" ;\ + ${MOCKERY_BIN} --all --dir $${dir} ;\ + fi ;\ + done ; + @echo "Mocks successfully created." diff --git a/build/make/variables.mk b/build/make/variables.mk index 964130e..639a8b1 100644 --- a/build/make/variables.mk +++ b/build/make/variables.mk @@ -19,7 +19,7 @@ GO_BUILD_TAG_INTEGRATION_TEST?=integration GOMODULES=on UTILITY_BIN_PATH?=${WORKDIR}/.bin -SRC:=$(shell find "${WORKDIR}" -type f -name "*.go" -not -path "./vendor/*") +SRC:=$(shell find "${WORKDIR}" -type f -name "*.go" -not -path "*/vendor/*") # debian stuff DEBIAN_BUILD_DIR=$(BUILD_DIR)/deb @@ -63,6 +63,10 @@ $(ETCGROUP): $(TMP_DIR) $(UTILITY_BIN_PATH): @mkdir -p $@ +# Subdirectories of workdir where no mocks should be generated. +# Multiple directories can be separated by space, comma or whatever is not a word to regex. +MOCKERY_IGNORED=vendor,build,docs + ##@ General .PHONY: help diff --git a/build/make/version-sha.mk b/build/make/version-sha.mk new file mode 100644 index 0000000..1335532 --- /dev/null +++ b/build/make/version-sha.mk @@ -0,0 +1,18 @@ +##@ Version + +# This makefile is used to get the sha256sum of a specific github tag-src.tar.gz or .zip. +# You may set any of the following variables before your make call to change the hash url. + +SHA_SUM_ORGANISATION?="cloudogu" +SHA_SUM_REPOSITORY?="ecosystem" +SHA_SUM_FILE_TYPE?="tar.gz" +SHA_SUM_VERSION?="v20.04.4-2" +SHA_SUM_URL?="https://github.com/${SHA_SUM_ORGANISATION}/${SHA_SUM_REPOSITORY}/archive/refs/tags/${SHA_SUM_VERSION}.${SHA_SUM_FILE_TYPE}" + +.PHONY: sha-sum +sha-sum: ## Print out the version + @echo "Downloading from: ${SHA_SUM_URL}" + @wget -O - -o /dev/null "${SHA_SUM_URL}" > .download.for.hash \ + || (echo "Could not be downloaded" && exit 1) \ + && cat .download.for.hash | sha256sum + @rm -f .download.for.hash diff --git a/config/crd/bases/k8s.cloudogu.com_backups.yaml b/config/crd/bases/k8s.cloudogu.com_backups.yaml new file mode 100644 index 0000000..334bccd --- /dev/null +++ b/config/crd/bases/k8s.cloudogu.com_backups.yaml @@ -0,0 +1,49 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: backups.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Backup + listKind: BackupList + plural: backups + singular: backup + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Backup is the Schema for the backups API + 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: BackupSpec defines the desired state of Backup + properties: + foo: + description: Foo is an example field of Backup. Edit backup_types.go + to remove/update + type: string + type: object + status: + description: BackupStatus defines the observed state of Backup + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/k8s.cloudogu.com_restores.yaml b/config/crd/bases/k8s.cloudogu.com_restores.yaml new file mode 100644 index 0000000..d314e7d --- /dev/null +++ b/config/crd/bases/k8s.cloudogu.com_restores.yaml @@ -0,0 +1,49 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: restores.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Restore + listKind: RestoreList + plural: restores + singular: restore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Restore is the Schema for the restores API + 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: RestoreSpec defines the desired state of Restore + properties: + foo: + description: Foo is an example field of Restore. Edit restore_types.go + to remove/update + type: string + type: object + status: + description: RestoreStatus defines the observed state of Restore + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml new file mode 100644 index 0000000..9064d82 --- /dev/null +++ b/config/crd/kustomization.yaml @@ -0,0 +1,24 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +- bases/k8s.cloudogu.com_restores.yaml +- bases/k8s.cloudogu.com_backups.yaml +#+kubebuilder:scaffold:crdkustomizeresource + +patches: +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. +# patches here are for enabling the conversion webhook for each CRD +#- path: patches/webhook_in_restores.yaml +#- path: patches/webhook_in_backups.yaml +#+kubebuilder:scaffold:crdkustomizewebhookpatch + +# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. +# patches here are for enabling the CA injection for each CRD +#- path: patches/cainjection_in_restores.yaml +#- path: patches/cainjection_in_backups.yaml +#+kubebuilder:scaffold:crdkustomizecainjectionpatch + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: +- kustomizeconfig.yaml diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml new file mode 100644 index 0000000..ec5c150 --- /dev/null +++ b/config/crd/kustomizeconfig.yaml @@ -0,0 +1,19 @@ +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false + +varReference: +- path: metadata/annotations diff --git a/config/crd/patches/cainjection_in_backups.yaml b/config/crd/patches/cainjection_in_backups.yaml new file mode 100644 index 0000000..f15758e --- /dev/null +++ b/config/crd/patches/cainjection_in_backups.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: backups.k8s.cloudogu.com diff --git a/config/crd/patches/cainjection_in_restores.yaml b/config/crd/patches/cainjection_in_restores.yaml new file mode 100644 index 0000000..d562b44 --- /dev/null +++ b/config/crd/patches/cainjection_in_restores.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: restores.k8s.cloudogu.com diff --git a/config/crd/patches/webhook_in_backups.yaml b/config/crd/patches/webhook_in_backups.yaml new file mode 100644 index 0000000..27247b8 --- /dev/null +++ b/config/crd/patches/webhook_in_backups.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: backups.k8s.cloudogu.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/crd/patches/webhook_in_restores.yaml b/config/crd/patches/webhook_in_restores.yaml new file mode 100644 index 0000000..fe80d64 --- /dev/null +++ b/config/crd/patches/webhook_in_restores.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: restores.k8s.cloudogu.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 77f205f..e188eef 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -7,11 +7,18 @@ # "wordpress" becomes "alices-wordpress". # Note that it should also match with the prefix (text before '-') of the namespace # field above. -namePrefix: k8s-backup-operator- +namePrefix: kubebuilder-backup-operator- -bases: -- ../rbac -- ../manager +# Labels to add to all resources and selectors. +#labels: +#- includeSelectors: true +# pairs: +# someName: someValue + +resources: + - ../crd + - ../rbac + - ../manager # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml #- ../webhook @@ -21,14 +28,12 @@ bases: #- ../prometheus patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml + # Protect the /metrics endpoint by putting it behind auth. + # If you want your controller-manager to expose the /metrics + # endpoint w/o any authn/z, please comment the following line. + - manager_auth_proxy_patch.yaml + -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -#- manager_config_patch.yaml # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml @@ -39,32 +44,102 @@ patchesStrategicMerge: # 'CERTMANAGER' needs to be enabled to use ca injection #- webhookcainjection_patch.yaml -# the following config is for teaching kustomize how to do var substitution -vars: # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service +# Uncomment the following replacements to add the cert-manager CA injection annotations +#replacements: +# - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldPath: .metadata.namespace # namespace of the certificate CR +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - select: +# kind: CustomResourceDefinition +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldPath: .metadata.name +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# - select: +# kind: CustomResourceDefinition +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# - source: # Add cert-manager annotation to the webhook Service +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.name # namespace of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 0 +# create: true +# - source: +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.namespace # namespace of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 1 +# create: true diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index 7ae9a4b..73fad2a 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -4,12 +4,18 @@ apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager + namespace: system spec: template: spec: containers: - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.14.1 args: - "--secure-listen-address=0.0.0.0:8443" - "--upstream=http://127.0.0.1:8080/" diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml index e846a37..b454087 100644 --- a/config/default/manager_config_patch.yaml +++ b/config/default/manager_config_patch.yaml @@ -7,13 +7,3 @@ spec: spec: containers: - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config diff --git a/config/labels/crd_label_patch.yaml b/config/labels/crd_label_patch.yaml new file mode 100644 index 0000000..83fabbf --- /dev/null +++ b/config/labels/crd_label_patch.yaml @@ -0,0 +1,7 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: backups.k8s.cloudogu.com + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator diff --git a/config/labels/kustomization.yaml b/config/labels/kustomization.yaml new file mode 100644 index 0000000..818a199 --- /dev/null +++ b/config/labels/kustomization.yaml @@ -0,0 +1,10 @@ +# Labels to add to all resources and selectors. +commonLabels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + +resources: +- ../crd + +patchesStrategicMerge: +- crd_label_patch.yaml diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml deleted file mode 100644 index 8249a38..0000000 --- a/config/manager/controller_manager_config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: 951e217a.cloudogu.com diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5da3c8b..5c5f0b8 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,14 +1,2 @@ resources: - manager.yaml -generatorOptions: - disableNameSuffixHash: true -configMapGenerator: -- files: - - controller_manager_config.yaml - name: manager-config -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -images: -- name: controller - newName: cloudogu/k8s-backup-operator - newTag: 0.19.0 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index b9a6fc7..6508554 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -1,70 +1,82 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: namespace + app.kubernetes.io/instance: system + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + name: system +--- apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager + namespace: system labels: control-plane: controller-manager + app.kubernetes.io/name: deployment + app.kubernetes.io/instance: controller-manager + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize spec: selector: matchLabels: control-plane: controller-manager replicas: 1 - strategy: - type: Recreate template: metadata: annotations: kubectl.kubernetes.io/default-container: manager labels: control-plane: controller-manager - app.kubernetes.io/name: k8s-backup-operator - app: ces spec: + # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # according to the platforms which are supported by your solution. + # It is considered best practice to support multiple architectures. You can + # build your manager image using the makefile target docker-buildx. + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/arch + # operator: In + # values: + # - amd64 + # - arm64 + # - ppc64le + # - s390x + # - key: kubernetes.io/os + # operator: In + # values: + # - linux securityContext: runAsNonRoot: true + # TODO(user): For common cases that do not require escalating privileges + # it is recommended to ensure that all your Pods/Containers are restrictive. + # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted + # Please uncomment the following code if your project does NOT have to work on old Kubernetes + # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). + # seccompProfile: + # type: RuntimeDefault containers: - - args: + - command: + - /manager + args: - --leader-elect - env: - - name: STAGE - value: "production" - - name: LOG_LEVEL - value: "debug" - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: DOGU_REGISTRY_ENDPOINT - valueFrom: - secretKeyRef: - name: k8s-backup-operator-dogu-registry - key: endpoint - - name: DOGU_REGISTRY_USERNAME - valueFrom: - secretKeyRef: - name: k8s-backup-operator-dogu-registry - key: username - - name: DOGU_REGISTRY_PASSWORD - valueFrom: - secretKeyRef: - name: k8s-backup-operator-dogu-registry - key: password - - name: DOGU_REGISTRY_URLSCHEMA - valueFrom: - secretKeyRef: - name: k8s-backup-operator-dogu-registry - key: urlschema - optional: true - - name: DOCKER_REGISTRY - valueFrom: - secretKeyRef: - name: k8s-backup-operator-docker-registry - key: .dockerconfigjson image: controller:latest - imagePullPolicy: IfNotPresent name: manager securityContext: allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" livenessProbe: httpGet: path: /healthz diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index d19136a..0ade53b 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -5,6 +5,12 @@ kind: ServiceMonitor metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: servicemonitor + app.kubernetes.io/instance: controller-manager-metrics-monitor + app.kubernetes.io/component: metrics + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-monitor namespace: system spec: diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml index b19981f..3d67e80 100644 --- a/config/rbac/auth_proxy_client_clusterrole.yaml +++ b/config/rbac/auth_proxy_client_clusterrole.yaml @@ -1,9 +1,16 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: metrics-reader + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: metrics-reader rules: - - nonResourceURLs: - - "/metrics" - verbs: - - get \ No newline at end of file +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml index 0e91929..fbe062b 100644 --- a/config/rbac/auth_proxy_role.yaml +++ b/config/rbac/auth_proxy_role.yaml @@ -1,6 +1,13 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: proxy-role + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: proxy-role rules: - apiGroups: diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index 5ee85d5..ebf905f 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -1,11 +1,19 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +kind: ClusterRoleBinding metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: proxy-rolebinding + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: proxy-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role + kind: ClusterRole name: proxy-role subjects: - kind: ServiceAccount name: controller-manager + namespace: system diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml index c54a533..8f332a7 100644 --- a/config/rbac/auth_proxy_service.yaml +++ b/config/rbac/auth_proxy_service.yaml @@ -3,7 +3,14 @@ kind: Service metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: service + app.kubernetes.io/instance: controller-manager-metrics-service + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-service + namespace: system spec: ports: - name: https diff --git a/config/rbac/backup_editor_role.yaml b/config/rbac/backup_editor_role.yaml new file mode 100644 index 0000000..699ecfa --- /dev/null +++ b/config/rbac/backup_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit backups. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: backup-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + name: backup-editor-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - backups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - backups/status + verbs: + - get diff --git a/config/rbac/backup_viewer_role.yaml b/config/rbac/backup_viewer_role.yaml new file mode 100644 index 0000000..2c0a497 --- /dev/null +++ b/config/rbac/backup_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view backups. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: backup-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + name: backup-viewer-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - backups + verbs: + - get + - list + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - backups/status + verbs: + - get diff --git a/config/rbac/cluster_role.yaml b/config/rbac/cluster_role.yaml deleted file mode 100644 index b55de59..0000000 --- a/config/rbac/cluster_role.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cluster-role - labels: - app: k8s-backup-operator - app.kubernetes.io/name: k8s-backup-operator -rules: - - apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - - clusterrolebindings - verbs: - - "*" \ No newline at end of file diff --git a/config/rbac/cluster_role_binding.yaml b/config/rbac/cluster_role_binding.yaml deleted file mode 100644 index 8c616f5..0000000 --- a/config/rbac/cluster_role_binding.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cluster-role-binding - labels: - app: k8s-backup-operator - app.kubernetes.io/name: k8s-backup-operator -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: k8s-backup-operator-cluster-role -subjects: - - kind: ServiceAccount - name: k8s-backup-operator-controller-manager - namespace: '{{ .Namespace }}' diff --git a/config/rbac/dogu_editor_role.yaml b/config/rbac/dogu_editor_role.yaml deleted file mode 100644 index 84999fb..0000000 --- a/config/rbac/dogu_editor_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# permissions for end users to edit dogus. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: dogu-editor-role -rules: -- apiGroups: - - k8s.cloudogu.com - resources: - - dogus - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - k8s.cloudogu.com - resources: - - dogus/status - verbs: - - get diff --git a/config/rbac/dogu_viewer_role.yaml b/config/rbac/dogu_viewer_role.yaml deleted file mode 100644 index 184626c..0000000 --- a/config/rbac/dogu_viewer_role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# permissions for end users to view dogus. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: dogu-viewer-role -rules: -- apiGroups: - - k8s.cloudogu.com - resources: - - dogus - verbs: - - get - - list - - watch -- apiGroups: - - k8s.cloudogu.com - resources: - - dogus/status - verbs: - - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index f1144cc..731832a 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -7,8 +7,6 @@ resources: - service_account.yaml - role.yaml - role_binding.yaml -- cluster_role.yaml -- cluster_role_binding.yaml - leader_election_role.yaml - leader_election_role_binding.yaml # Comment the following 4 lines if you want to disable diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml index 4190ec8..592e4a5 100644 --- a/config/rbac/leader_election_role.yaml +++ b/config/rbac/leader_election_role.yaml @@ -2,6 +2,13 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: + labels: + app.kubernetes.io/name: role + app.kubernetes.io/instance: leader-election-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: leader-election-role rules: - apiGroups: diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml index df9defb..3514b04 100644 --- a/config/rbac/leader_election_role_binding.yaml +++ b/config/rbac/leader_election_role_binding.yaml @@ -1,6 +1,13 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: + labels: + app.kubernetes.io/name: rolebinding + app.kubernetes.io/instance: leader-election-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: leader-election-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io @@ -9,3 +16,4 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager + namespace: system diff --git a/config/rbac/restore_editor_role.yaml b/config/rbac/restore_editor_role.yaml new file mode 100644 index 0000000..fa1ea21 --- /dev/null +++ b/config/rbac/restore_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit restores. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: restore-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + name: restore-editor-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - restores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - restores/status + verbs: + - get diff --git a/config/rbac/restore_viewer_role.yaml b/config/rbac/restore_viewer_role.yaml new file mode 100644 index 0000000..1966ec1 --- /dev/null +++ b/config/rbac/restore_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view restores. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: restore-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + name: restore-viewer-role +rules: +- apiGroups: + - k8s.cloudogu.com + resources: + - restores + verbs: + - get + - list + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - restores/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 11b5244..29806d2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,12 +1,58 @@ --- apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: name: manager-role rules: - apiGroups: - - "*" + - k8s.cloudogu.com resources: - - "*" + - backups verbs: - - "*" + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - backups/finalizers + verbs: + - update +- apiGroups: + - k8s.cloudogu.com + resources: + - backups/status + verbs: + - get + - patch + - update +- apiGroups: + - k8s.cloudogu.com + resources: + - restores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.cloudogu.com + resources: + - restores/finalizers + verbs: + - update +- apiGroups: + - k8s.cloudogu.com + resources: + - restores/status + verbs: + - get + - patch + - update diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index 5e11a2f..0f226fb 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -1,11 +1,19 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +kind: ClusterRoleBinding metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: manager-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role + kind: ClusterRole name: manager-role subjects: - kind: ServiceAccount name: controller-manager + namespace: system diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml index 69ece2e..0433299 100644 --- a/config/rbac/service_account.yaml +++ b/config/rbac/service_account.yaml @@ -1,4 +1,12 @@ apiVersion: v1 kind: ServiceAccount metadata: + labels: + app.kubernetes.io/name: serviceaccount + app.kubernetes.io/instance: controller-manager-sa + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager + namespace: system diff --git a/config/samples/cas_config.sh b/config/samples/cas_config.sh deleted file mode 100644 index d49a7df..0000000 --- a/config/samples/cas_config.sh +++ /dev/null @@ -1,10 +0,0 @@ -kubectl exec -it etcd-client -- etcdctl set "config/cas/ldap/ds_type" "embedded" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_id" "uid" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_group" "memberof" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_mail" "mail" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/search_filter" "(objectClass=person)" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/attribute_fullname" "cn" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/encryption" "none" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/host" "ldap" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/ldap/port" "389" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/cas/logging/root" "DEBUG" \ No newline at end of file diff --git a/config/samples/hallowelt/bluespice-pdfrenderer.yaml b/config/samples/hallowelt/bluespice-pdfrenderer.yaml deleted file mode 100644 index 0150b03..0000000 --- a/config/samples/hallowelt/bluespice-pdfrenderer.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: bluespice-pdfrenderer - annotations: - test: dev - labels: - dogu.name: bluespice-pdfrenderer - app: ces -spec: - name: hallowelt/bluespice-pdfrenderer - version: 4.2.1-1 \ No newline at end of file diff --git a/config/samples/hallowelt/bluespice.yaml b/config/samples/hallowelt/bluespice.yaml deleted file mode 100644 index 919d4da..0000000 --- a/config/samples/hallowelt/bluespice.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: bluespice - annotations: - test: dev - labels: - dogu.name: bluespice - app: ces -spec: - name: hallowelt/bluespice - version: 4.2.3-2 \ No newline at end of file diff --git a/config/samples/hallowelt/drawio.yaml b/config/samples/hallowelt/drawio.yaml deleted file mode 100644 index 36181bc..0000000 --- a/config/samples/hallowelt/drawio.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: drawio - annotations: - test: dev - labels: - dogu.name: drawio - app: ces -spec: - name: hallowelt/drawio - version: 20.3.7-1 \ No newline at end of file diff --git a/config/samples/itz-bund/teamscale.yaml b/config/samples/itz-bund/teamscale.yaml deleted file mode 100644 index 2ef4e3f..0000000 --- a/config/samples/itz-bund/teamscale.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: teamscale - annotations: - test: dev - labels: - dogu.name: teamscale - app: ces -spec: - name: itz-bund/teamscale - version: 8.4.0-1 \ No newline at end of file diff --git a/config/samples/k8s/nginx-ingress.yaml b/config/samples/k8s/nginx-ingress.yaml deleted file mode 100644 index 7c57897..0000000 --- a/config/samples/k8s/nginx-ingress.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: nginx-ingress - annotations: - test: dev - labels: - dogu.name: nginx-ingress - app: nginx-ingress -spec: - name: k8s/nginx-ingress - version: 1.3.0-2 \ No newline at end of file diff --git a/config/samples/k8s/nginx-static.yaml b/config/samples/k8s/nginx-static.yaml deleted file mode 100644 index 812d702..0000000 --- a/config/samples/k8s/nginx-static.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: nginx-static - annotations: - test: dev - labels: - dogu.name: nginx-static - app: nginx-static -spec: - name: k8s/nginx-static - version: 1.23.1-3 \ No newline at end of file diff --git a/config/samples/k8s_v1_backup.yaml b/config/samples/k8s_v1_backup.yaml new file mode 100644 index 0000000..3678b90 --- /dev/null +++ b/config/samples/k8s_v1_backup.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Backup +metadata: + labels: + app.kubernetes.io/name: backup + app.kubernetes.io/instance: backup-sample + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: kubebuilder-backup-operator + name: backup-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/k8s_v1_dogu.yaml b/config/samples/k8s_v1_dogu.yaml deleted file mode 100644 index bf9a550..0000000 --- a/config/samples/k8s_v1_dogu.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: dogu-sample -spec: - name: official/postfix - version: 3.6.4-3 - supportMode: false \ No newline at end of file diff --git a/config/samples/k8s_v1_restore.yaml b/config/samples/k8s_v1_restore.yaml new file mode 100644 index 0000000..91be4e0 --- /dev/null +++ b/config/samples/k8s_v1_restore.yaml @@ -0,0 +1,12 @@ +apiVersion: k8s.cloudogu.com/v1 +kind: Restore +metadata: + labels: + app.kubernetes.io/name: restore + app.kubernetes.io/instance: restore-sample + app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: kubebuilder-backup-operator + name: restore-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml new file mode 100644 index 0000000..8b7572b --- /dev/null +++ b/config/samples/kustomization.yaml @@ -0,0 +1,5 @@ +## Append samples of your project ## +resources: +- k8s_v1_restore.yaml +- k8s_v1_backup.yaml +#+kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/ldap-mapper.sh b/config/samples/ldap-mapper.sh deleted file mode 100644 index ec963aa..0000000 --- a/config/samples/ldap-mapper.sh +++ /dev/null @@ -1,3 +0,0 @@ -kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/type" "embedded" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/host" "ldap" \ -&& kubectl exec -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/port" "389" \ No newline at end of file diff --git a/config/samples/ldap_config.sh b/config/samples/ldap_config.sh deleted file mode 100644 index 1c8637d..0000000 --- a/config/samples/ldap_config.sh +++ /dev/null @@ -1,2 +0,0 @@ -kubectl exec -it etcd-client -- etcdctl set "config/ldap/admin_mail" "mail@test.de" \ -&& kubectl exec -it etcd-client -- etcdctl set "config/ldap/admin_member" "true" \ No newline at end of file diff --git a/config/samples/official/backup.yaml b/config/samples/official/backup.yaml deleted file mode 100644 index 96e66a5..0000000 --- a/config/samples/official/backup.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: backup - annotations: - test: dev - labels: - dogu.name: backup - app: backup -spec: - name: premium/backup - version: 1.9.2-2 \ No newline at end of file diff --git a/config/samples/official/cas.yaml b/config/samples/official/cas.yaml deleted file mode 100644 index 85057a8..0000000 --- a/config/samples/official/cas.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: cas - annotations: - test: dev - labels: - dogu.name: cas - app: ces -spec: - name: official/cas - version: 6.5.5-4 \ No newline at end of file diff --git a/config/samples/official/cas_config.sh b/config/samples/official/cas_config.sh deleted file mode 100755 index 5fcb39b..0000000 --- a/config/samples/official/cas_config.sh +++ /dev/null @@ -1,10 +0,0 @@ -kubectl exec --namespace ecosystem etcd-client -- etcdctl set "config/cas/ldap/ds_type" "embedded" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_id" "uid" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_group" "memberof" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_mail" "mail" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/search_filter" "(objectClass=person)" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/attribute_fullname" "cn" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/encryption" "none" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/host" "ldap" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/ldap/port" "389" \ -&& kubectl exec --namespace ecosystem etcd-client -- etcdctl set "/config/cas/logging/root" "DEBUG" \ No newline at end of file diff --git a/config/samples/official/cockpit.yaml b/config/samples/official/cockpit.yaml deleted file mode 100644 index 1da3de6..0000000 --- a/config/samples/official/cockpit.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: cockpit - annotations: - test: dev - labels: - dogu.name: cockpit - app: ces -spec: - name: official/cockpit - version: 2.0.2-5 \ No newline at end of file diff --git a/config/samples/official/elasticsearch.yaml b/config/samples/official/elasticsearch.yaml deleted file mode 100644 index 6c50f6e..0000000 --- a/config/samples/official/elasticsearch.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: elasticsearch - annotations: - test: dev - labels: - dogu.name: drawio - app: elasticsearch -spec: - name: official/elasticsearch - version: 6.8.23-3 \ No newline at end of file diff --git a/config/samples/official/gotenberg.yaml b/config/samples/official/gotenberg.yaml deleted file mode 100644 index a061817..0000000 --- a/config/samples/official/gotenberg.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: gotenberg - annotations: - test: dev - labels: - dogu.name: gotenberg - app: ces -spec: - name: official/gotenberg - version: 7.5.2-1 \ No newline at end of file diff --git a/config/samples/official/jenkins.yaml b/config/samples/official/jenkins.yaml deleted file mode 100644 index 6697ad4..0000000 --- a/config/samples/official/jenkins.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: jenkins - annotations: - test: dev - labels: - dogu.name: jenkins - app: ces -spec: - name: official/jenkins - version: 2.346.1-1 \ No newline at end of file diff --git a/config/samples/official/ldap-mapper.sh b/config/samples/official/ldap-mapper.sh deleted file mode 100755 index 578faef..0000000 --- a/config/samples/official/ldap-mapper.sh +++ /dev/null @@ -1,3 +0,0 @@ -kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/type" "embedded" \ -&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/host" "ldap" \ -&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "/config/ldap-mapper/backend/port" "389" \ No newline at end of file diff --git a/config/samples/official/ldap-mapper.yaml b/config/samples/official/ldap-mapper.yaml deleted file mode 100644 index 9f59ce4..0000000 --- a/config/samples/official/ldap-mapper.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: ldap-mapper - annotations: - test: dev - labels: - dogu.name: ldap-mapper - app: ces -spec: - name: official/ldap-mapper - version: 1.3.0 \ No newline at end of file diff --git a/config/samples/official/ldap.yaml b/config/samples/official/ldap.yaml deleted file mode 100644 index 586d894..0000000 --- a/config/samples/official/ldap.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: ldap - annotations: - test: dev - labels: - dogu.name: ldap - app: ces -spec: - name: official/ldap - version: 2.6.2-2 \ No newline at end of file diff --git a/config/samples/official/ldap_config.sh b/config/samples/official/ldap_config.sh deleted file mode 100755 index d5f2a73..0000000 --- a/config/samples/official/ldap_config.sh +++ /dev/null @@ -1,2 +0,0 @@ -kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/ldap/admin_mail" "mail@test.de" \ -&& kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/ldap/admin_member" "true" \ No newline at end of file diff --git a/config/samples/official/mysql.yaml b/config/samples/official/mysql.yaml deleted file mode 100644 index 99407e0..0000000 --- a/config/samples/official/mysql.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: mysql - annotations: - test: dev - labels: - dogu.name: mysql - app: ces -spec: - name: official/mysql - version: 5.7.37-4 \ No newline at end of file diff --git a/config/samples/official/nexus.yaml b/config/samples/official/nexus.yaml deleted file mode 100644 index 0158e4f..0000000 --- a/config/samples/official/nexus.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: nexus - annotations: - test: dev - labels: - dogu.name: nexus - app: ces -spec: - name: official/nexus - version: 3.40.1-2 \ No newline at end of file diff --git a/config/samples/official/plantuml.yaml b/config/samples/official/plantuml.yaml deleted file mode 100644 index 56ef277..0000000 --- a/config/samples/official/plantuml.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: plantuml - annotations: - test: dev - labels: - dogu.name: plantuml - app: ces -spec: - name: official/plantuml - version: 2022.4-1 \ No newline at end of file diff --git a/config/samples/official/postfix.yaml b/config/samples/official/postfix.yaml deleted file mode 100644 index fd2801a..0000000 --- a/config/samples/official/postfix.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: postfix - annotations: - test: dev - labels: - dogu.name: postfix - app: ces -spec: - name: official/postfix - version: 3.6.4-3 - resources: - dataVolumeSize: "4Gi" diff --git a/config/samples/official/postfix_config.sh b/config/samples/official/postfix_config.sh deleted file mode 100755 index 65a70a6..0000000 --- a/config/samples/official/postfix_config.sh +++ /dev/null @@ -1 +0,0 @@ -kubectl exec --namespace ecosystem -it etcd-client -- etcdctl set "config/postfix/relayhost" "mail.mydomain.com" \ No newline at end of file diff --git a/config/samples/official/postgresql.yaml b/config/samples/official/postgresql.yaml deleted file mode 100644 index 9d50d76..0000000 --- a/config/samples/official/postgresql.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: postgresql - annotations: - test: dev - labels: - dogu.name: postgresql - app: ces -spec: - name: official/postgresql - version: 12.10-1 - resources: - dataVolumeSize: "1Gi" diff --git a/config/samples/official/redis.yaml b/config/samples/official/redis.yaml deleted file mode 100644 index 10858a1..0000000 --- a/config/samples/official/redis.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: redis - annotations: - test: dev - labels: - dogu.name: redis - app: ces -spec: - name: official/redis - version: 6.2.6-2 \ No newline at end of file diff --git a/config/samples/official/redmine.yaml b/config/samples/official/redmine.yaml deleted file mode 100644 index 899829e..0000000 --- a/config/samples/official/redmine.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: redmine - annotations: - test: dev - labels: - dogu.name: redmine - app: ces -spec: - name: official/redmine - version: 4.2.5-1 \ No newline at end of file diff --git a/config/samples/official/scm.yaml b/config/samples/official/scm.yaml deleted file mode 100644 index 8c739dd..0000000 --- a/config/samples/official/scm.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: scm - annotations: - test: dev - labels: - dogu.name: scm - app: ces -spec: - name: official/scm - version: 2.40.0-1 -# version: 2.39.1-1 \ No newline at end of file diff --git a/config/samples/official/smeagol.yaml b/config/samples/official/smeagol.yaml deleted file mode 100644 index ccf011d..0000000 --- a/config/samples/official/smeagol.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: smeagol - annotations: - test: dev - labels: - dogu.name: smeagol - app: ces -spec: - name: official/smeagol - version: 1.6.2-2 \ No newline at end of file diff --git a/config/samples/official/sonar.yaml b/config/samples/official/sonar.yaml deleted file mode 100644 index ddce5fc..0000000 --- a/config/samples/official/sonar.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: sonar - annotations: - test: dev - labels: - dogu.name: sonar - app: ces -spec: - name: official/sonar - version: 8.9.8-2 \ No newline at end of file diff --git a/config/samples/official/swaggerui.yaml b/config/samples/official/swaggerui.yaml deleted file mode 100644 index b1e923f..0000000 --- a/config/samples/official/swaggerui.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: swaggerui - annotations: - test: dev - labels: - dogu.name: swaggerui - app: ces -spec: - name: official/swaggerui - version: 4.9.0-1 \ No newline at end of file diff --git a/config/samples/official/usermgt.yaml b/config/samples/official/usermgt.yaml deleted file mode 100644 index c43ceaa..0000000 --- a/config/samples/official/usermgt.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: usermgt - annotations: - test: dev - labels: - dogu.name: usermgt - app: ces -spec: - name: official/usermgt - version: 1.7.0-1 - resources: - dataVolumeSize: "6Gi" \ No newline at end of file diff --git a/config/samples/postfix_config.sh b/config/samples/postfix_config.sh deleted file mode 100644 index a2f5fe8..0000000 --- a/config/samples/postfix_config.sh +++ /dev/null @@ -1 +0,0 @@ -kubectl exec -it etcd-client -- etcdctl set "config/postfix/relayhost" "mail.mydomain.com" \ No newline at end of file diff --git a/config/samples/premium/admin.yaml b/config/samples/premium/admin.yaml deleted file mode 100644 index cb4b98a..0000000 --- a/config/samples/premium/admin.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: admin - annotations: - test: dev - labels: - dogu.name: admin - app: ces -spec: - name: premium/admin - version: 2.6.2-1 \ No newline at end of file diff --git a/config/samples/premium/confluence.yaml b/config/samples/premium/confluence.yaml deleted file mode 100644 index ec1795e..0000000 --- a/config/samples/premium/confluence.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: confluence - annotations: - test: dev - labels: - dogu.name: confluence - app: ces -spec: - name: premium/confluence - version: 7.13.8-1 \ No newline at end of file diff --git a/config/samples/premium/jira.yaml b/config/samples/premium/jira.yaml deleted file mode 100644 index f1388ae..0000000 --- a/config/samples/premium/jira.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: k8s.cloudogu.com/v1 -kind: Dogu -metadata: - name: jira - annotations: - test: dev - labels: - dogu.name: jira - app: ces -spec: - name: premium/jira - version: 8.20.13-1 \ No newline at end of file diff --git a/go.mod b/go.mod index 5a949d7..acc2634 100644 --- a/go.mod +++ b/go.mod @@ -1,107 +1,70 @@ module github.com/cloudogu/k8s-backup-operator -go 1.18 +go 1.21 require ( - github.com/bombsimon/logrusr/v2 v2.0.1 - github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473 - github.com/cloudogu/k8s-apply-lib v0.4.0 - github.com/go-logr/logr v1.2.3 - github.com/google/go-cmp v0.5.8 - github.com/google/go-containerregistry v0.8.0 - github.com/hashicorp/go-multierror v1.1.1 - github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.19.0 - github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.8.1 - go.etcd.io/etcd/client/v2 v2.305.4 - golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c - k8s.io/api v0.24.4 - k8s.io/apimachinery v0.24.4 - k8s.io/client-go v0.24.4 - k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 - sigs.k8s.io/controller-runtime v0.12.3 - sigs.k8s.io/yaml v1.3.0 + github.com/Masterminds/semver/v3 v3.2.1 + k8s.io/apimachinery v0.28.1 + k8s.io/client-go v0.28.1 + sigs.k8s.io/controller-runtime v0.16.0 ) -replace google.golang.org/grpc => google.golang.org/grpc v1.29.0 - require ( - cloud.google.com/go/compute v1.9.0 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.28 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.10.1 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docker/cli v20.10.12+incompatible // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.12+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.4 // indirect - github.com/eapache/go-resiliency v1.3.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/gnostic v0.6.9 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.13.6 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moby/spdystream v0.2.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.13.0 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/vbatts/tar-split v0.11.2 // indirect - go.etcd.io/etcd/api/v3 v3.5.4 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect - golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect - golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect - golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.25.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/net v0.13.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.24.4 // indirect - k8s.io/component-base v0.24.4 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + k8s.io/api v0.28.1 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/component-base v0.28.0 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index f9eda69..b797d7b 100644 --- a/go.sum +++ b/go.sum @@ -1,1588 +1,305 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.9.0 h1:ED/FP4xv8GJw63v556/ASNc1CeeLUO2Bs8nzaHchkHg= -cloud.google.com/go/compute v1.9.0/go.mod h1:lWv1h/zUWTm/LozzfTJhBSkd6ShQq8la8VeeuOEGxfY= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -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= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -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.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= -github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -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/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= -github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= -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.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -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/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -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= -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/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +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-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= -github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473 h1:cRZXYR4/bd+IUlBXnmlVj3kOQiluqJtwCpBiTgO6cCg= -github.com/cloudogu/cesapp-lib v0.0.0-20221229112545-4d449f4c8473/go.mod h1:PTQqI3xs1ReJMXYE6BGTF33yAfmS4J7P8UiE4AwDMDY= -github.com/cloudogu/k8s-apply-lib v0.4.0 h1:4jYj0gTDSvW0qs9d5yM5w8aOsMu5Sx+PBCwJwa5sMss= -github.com/cloudogu/k8s-apply-lib v0.4.0/go.mod h1:WHCe588o8e1vzNdLGV6N4E0g7BarbPXPpW4y8U0/lxE= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng= -github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -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/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= 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= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= -github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U= -github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -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/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/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0= -github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= -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= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -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/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= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.0.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/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.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= +github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.8.0 h1:mtR24eN6rapCN+shds82qFEIWWmg64NPMuyCNT7/Ogc= -github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -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/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -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/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -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.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -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= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -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.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -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/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= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/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/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -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/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -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-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -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/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= 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-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.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.10.3/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.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 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= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -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/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -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/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -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/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -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.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= 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/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/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= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -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= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= -github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -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/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= -go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= -go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -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.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -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.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= +go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= +go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= +go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= +go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= +go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-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-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 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= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c= -golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20181011144130-49bb7cea24b1/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= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes= -golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 h1:2o1E+E8TpNLklK9nHiPiK1uzIYrIHt+cQx3ynCwq9V8= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190312061237-fead79001313/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= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= -golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -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= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -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-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= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -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= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= 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.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -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= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/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= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -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/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= -k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= -k8s.io/apiextensions-apiserver v0.24.4 h1:w53Pm4zu8fCt9WfiRgS2YI6LE6I4NJ5aUi78GElD3K8= -k8s.io/apiextensions-apiserver v0.24.4/go.mod h1:iDK+Xb4jsPNnRGj5jU/WqqjLvt8363M7cKixKe1C9+U= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= -k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.24.4/go.mod h1:mAuC3pZVc0IDXLx7lUHoisBOtBa1SobfLW/CI3klXQE= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= -k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= -k8s.io/code-generator v0.24.4/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.24.4 h1:WEGRp06GBYVwxp5JdiRaJ1zkdOhrqucxRv/8IrABLG0= -k8s.io/component-base v0.24.4/go.mod h1:sWxkgcMfbYHadw0OJ0N+vIscd14/nqSIM2veCdg843o= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -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.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea h1:3QOH5+2fGsY8e1qf+GIFpg+zw/JGNrgyZRQR7/m6uWg= -k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 h1:XmRqFcQlCy/lKRZ39j+RVpokYNroHPqV3mcBRfnhT5o= -k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -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.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/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/controller-runtime v0.12.3 h1:FCM8xeY/FI8hoAfh/V4XbbYMY20gElh9yh+A98usMio= -sigs.k8s.io/controller-runtime v0.12.3/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= +k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= +k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= +k8s.io/apiserver v0.28.0 h1:wVh7bK6Xj7hq+5ntInysTeQRAOqqFoKGUOW2yj8DXrY= +k8s.io/apiserver v0.28.0/go.mod h1:MvLmtxhQ0Tb1SZk4hfJBjs8iqr5nhYeaFSaoEcz7Lk4= +k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= +k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= +k8s.io/component-base v0.28.0 h1:HQKy1enJrOeJlTlN4a6dU09wtmXaUvThC0irImfqyxI= +k8s.io/component-base v0.28.0/go.mod h1:Yyf3+ZypLfMydVzuLBqJ5V7Kx6WwDr/5cN+dFjw1FNk= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.28.0 h1:BwJhU9qPcJhHLUcQjtelOSjYti+1/caJLr+4jHbKzTA= +k8s.io/kms v0.28.0/go.mod h1:CNU792ls92v2Ye7Vn1jn+xLqYtUSezDZNVu6PLbJyrU= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= +sigs.k8s.io/controller-runtime v0.16.0 h1:5koYaaRVBHDr0LZAJjO5dWzUjMsh6cwa7q1Mmusrdvk= +sigs.k8s.io/controller-runtime v0.16.0/go.mod h1:77DnuwA8+J7AO0njzv3wbNlMOnGuLrwFr8JPNwx3J7g= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/main.go b/main.go index 4864d5b..1e3e0de 100644 --- a/main.go +++ b/main.go @@ -3,32 +3,33 @@ package main import ( "flag" "fmt" - "github.com/cloudogu/k8s-backup-operator/pkg/config" - "github.com/cloudogu/k8s-backup-operator/pkg/controllers" - "github.com/cloudogu/k8s-backup-operator/pkg/logging" "os" - "sigs.k8s.io/controller-runtime/pkg/manager" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" - // +kubebuilder:scaffold:imports + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/cloudogu/k8s-backup-operator/pkg/api/ecosystem" + k8sv1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + "github.com/cloudogu/k8s-backup-operator/pkg/config" + "github.com/cloudogu/k8s-backup-operator/pkg/controllers" + //+kubebuilder:scaffold:imports ) var ( - scheme = runtime.NewScheme() - // set up the logger before the actual logger is instantiated - // the logger will be replaced later-on with a more sophisticated instance - setupLog = ctrl.Log.WithName("setup") - metricsAddr string - enableLeaderElection bool - probeAddr string + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") ) var ( @@ -38,7 +39,9 @@ var ( func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - // +kubebuilder:scaffold:scheme + utilruntime.Must(k8sv1.AddToScheme(scheme)) + + //+kubebuilder:scaffold:scheme } func main() { @@ -50,99 +53,102 @@ func main() { } func startOperator() error { - err := logging.ConfigureLogger() - if err != nil { - return err - } - operatorConfig, err := config.NewOperatorConfig(Version) - if err != nil { - return fmt.Errorf("failed to create new operator configuration: %w", err) - } options := getK8sManagerOptions(operatorConfig) k8sManager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) if err != nil { - return fmt.Errorf("failed to start manager: %w", err) + return fmt.Errorf("unable to start manager: %w", err) } err = configureManager(k8sManager, operatorConfig) if err != nil { - return fmt.Errorf("failed to configure manager: %w", err) + return fmt.Errorf("unable to configure manager: %w", err) } - // print starting info to stderr; we don't use the logger here because by default the level must be ERROR - println("Starting manager...") - return startK8sManager(k8sManager) } func configureManager(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { - err := configureReconciler(k8sManager, operatorConfig) + err := configureReconcilers(k8sManager, operatorConfig) if err != nil { - return fmt.Errorf("failed to configure reconciler: %w", err) + return fmt.Errorf("unable to configure reconciler: %w", err) } - // +kubebuilder:scaffold:builder err = addChecks(k8sManager) if err != nil { - return fmt.Errorf("failed to add checks to the manager: %w", err) + return fmt.Errorf("unable to add checks to the manager: %w", err) } return nil } -func getK8sManagerOptions(operatorConfig *config.OperatorConfig) manager.Options { +func getK8sManagerOptions(operatorConfig *config.OperatorConfig) ctrl.Options { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") - - options := ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - Namespace: operatorConfig.Namespace, + opts := zap.Options{ + Development: config.IsStageDevelopment(), + } + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + return ctrl.Options{ + Scheme: scheme, + Metrics: server.Options{BindAddress: metricsAddr}, + Cache: cache.Options{DefaultNamespaces: map[string]cache.Config{ + operatorConfig.Namespace: {}, + }}, + WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, - LeaderElectionID: "951e217a.cloudogu.com", + LeaderElectionID: "e3f6c1a7.cloudogu.com", } - - return options } -func startK8sManager(k8sManager manager.Manager) error { - setupLog.Info("starting manager") - err := k8sManager.Start(ctrl.SetupSignalHandler()) +func configureReconcilers(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { + eventRecorder := k8sManager.GetEventRecorderFor("k8s-backup-operator") + + k8sClientSet, err := kubernetes.NewForConfig(k8sManager.GetConfig()) if err != nil { - return fmt.Errorf("failed to start manager: %w", err) + return fmt.Errorf("unable to create clientset: %w", err) } - return nil -} - -func configureReconciler(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { - eventRecorder := k8sManager.GetEventRecorderFor("k8s-backup-operator") - backupReconciler := controllers.NewBackupReconciler(k8sManager.GetClient(), eventRecorder) + ecosystemClientSet, err := ecosystem.NewClientSet(k8sManager.GetConfig(), k8sClientSet) - err := backupReconciler.SetupWithManager(k8sManager) - if err != nil { - return fmt.Errorf("failed to setup reconciler with manager: %w", err) + if err = (controller.NewRestoreReconciler(ecosystemClientSet, eventRecorder, operatorConfig.Namespace)).SetupWithManager(k8sManager); err != nil { + return fmt.Errorf("unable to create restore controller: %w", err) + } + if err = (controller.NewBackupReconciler(ecosystemClientSet, eventRecorder, operatorConfig.Namespace)).SetupWithManager(k8sManager); err != nil { + return fmt.Errorf("unable to create backup controller: %w", err) } + // +kubebuilder:scaffold:builder return nil } -func addChecks(mgr manager.Manager) error { - err := mgr.AddHealthzCheck("healthz", healthz.Ping) - if err != nil { - return fmt.Errorf("failed to add healthz check: %w", err) +func addChecks(k8sManager manager.Manager) error { + if err := k8sManager.AddHealthzCheck("healthz", healthz.Ping); err != nil { + return fmt.Errorf("unable to set up health check: %w", err) + } + if err := k8sManager.AddReadyzCheck("readyz", healthz.Ping); err != nil { + return fmt.Errorf("unable to set up ready check: %w", err) } - err = mgr.AddReadyzCheck("readyz", healthz.Ping) - if err != nil { - return fmt.Errorf("failed to add readyz check: %w", err) + return nil +} + +func startK8sManager(k8sManager manager.Manager) error { + setupLog.Info("starting manager") + if err := k8sManager.Start(ctrl.SetupSignalHandler()); err != nil { + return fmt.Errorf("problem running manager: %w", err) } return nil diff --git a/main_internal_test.go b/main_internal_test.go deleted file mode 100644 index ed89e92..0000000 --- a/main_internal_test.go +++ /dev/null @@ -1,165 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - - "os" - "testing" - - "github.com/cloudogu/k8s-backup-operator/pkg/mocks/external" - - "github.com/go-logr/logr" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" - "sigs.k8s.io/controller-runtime/pkg/manager" -) - -type mockDefinition struct { - Arguments []interface{} - ReturnValue interface{} -} - -func getCopyMap(definitions map[string]mockDefinition) map[string]mockDefinition { - newCopyMap := map[string]mockDefinition{} - for k, v := range definitions { - newCopyMap[k] = v - } - return newCopyMap -} - -func getNewMockManager(expectedErrorOnNewManager error, definitions map[string]mockDefinition) manager.Manager { - k8sManager := &external.Manager{} - ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { - for key, value := range definitions { - k8sManager.Mock.On(key, value.Arguments...).Return(value.ReturnValue) - } - return k8sManager, expectedErrorOnNewManager - } - ctrl.SetLogger = func(l logr.Logger) { - k8sManager.Mock.On("GetLogger").Return(l) - } - flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError) - - return k8sManager -} - -func Test_startDoguOperator(t *testing.T) { - // override default controller method to create a new manager - oldNewManagerDelegate := ctrl.NewManager - defer func() { ctrl.NewManager = oldNewManagerDelegate }() - - // override default controller method to retrieve a kube config - oldGetConfigOrDieDelegate := ctrl.GetConfigOrDie - defer func() { ctrl.GetConfigOrDie = oldGetConfigOrDieDelegate }() - ctrl.GetConfigOrDie = func() *rest.Config { - return &rest.Config{} - } - - // override default controller method to retrieve a kube config - oldGetConfigDelegate := ctrl.GetConfig - defer func() { ctrl.GetConfig = oldGetConfigDelegate }() - ctrl.GetConfig = func() (*rest.Config, error) { - return &rest.Config{}, nil - } - - // override default controller method to signal the setup handler - oldHandler := ctrl.SetupSignalHandler - defer func() { ctrl.SetupSignalHandler = oldHandler }() - ctrl.SetupSignalHandler = func() context.Context { - return context.TODO() - } - - // override default controller method to retrieve a kube config - oldSetLoggerDelegate := ctrl.SetLogger - defer func() { ctrl.SetLogger = oldSetLoggerDelegate }() - - scheme := runtime.NewScheme() - utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - myClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - defaultMockDefinitions := map[string]mockDefinition{ - "GetScheme": {ReturnValue: scheme}, - "GetClient": {ReturnValue: myClient}, - "Add": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, - "AddHealthzCheck": {Arguments: []interface{}{mock.Anything, mock.Anything}, ReturnValue: nil}, - "AddReadyzCheck": {Arguments: []interface{}{mock.Anything, mock.Anything}, ReturnValue: nil}, - "Start": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, - "GetControllerOptions": {ReturnValue: v1alpha1.ControllerConfigurationSpec{}}, - "SetFields": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, - "GetEventRecorderFor": {Arguments: []interface{}{mock.Anything}, ReturnValue: nil}, - } - - t.Run("Error on missing namespace environment variable", func(t *testing.T) { - // given - _ = os.Unsetenv("NAMESPACE") - getNewMockManager(nil, defaultMockDefinitions) - - // when - err := startOperator() - - // then - require.Error(t, err) - require.Contains(t, err.Error(), "failed to read namespace: failed to get env var [NAMESPACE]") - }) - - t.Setenv("NAMESPACE", "mynamespace") - t.Run("Test without logger environment variables", func(t *testing.T) { - // given - k8sManager := getNewMockManager(nil, defaultMockDefinitions) - - // when - err := startOperator() - - // then - require.NoError(t, err) - mock.AssertExpectationsForObjects(t, k8sManager) - }) - - expectedError := fmt.Errorf("this is my expected error") - - t.Run("Test with error on manager creation", func(t *testing.T) { - // given - getNewMockManager(expectedError, defaultMockDefinitions) - - // when - err := startOperator() - - // then - require.ErrorIs(t, err, expectedError) - }) - - mockDefinitionsThatCanFail := []string{ - "Add", - "AddHealthzCheck", - "AddReadyzCheck", - "Start", - "SetFields", - } - - for _, mockDefinitionName := range mockDefinitionsThatCanFail { - t.Run(fmt.Sprintf("fail setup when error on %s", mockDefinitionName), func(t *testing.T) { - // given - adaptedMockDefinitions := getCopyMap(defaultMockDefinitions) - adaptedMockDefinitions[mockDefinitionName] = mockDefinition{ - Arguments: adaptedMockDefinitions[mockDefinitionName].Arguments, - ReturnValue: expectedError, - } - getNewMockManager(nil, adaptedMockDefinitions) - - // when - err := startOperator() - - // then - require.ErrorIs(t, err, expectedError) - }) - } -} diff --git a/pkg/api/ecosystem/backupRestClient.go b/pkg/api/ecosystem/backupRestClient.go new file mode 100644 index 0000000..c73800f --- /dev/null +++ b/pkg/api/ecosystem/backupRestClient.go @@ -0,0 +1,251 @@ +package ecosystem + +import ( + "context" + "fmt" + "time" + + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + "github.com/cloudogu/k8s-backup-operator/pkg/retry" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +type BackupInterface interface { + // Create takes the representation of a backup and creates it. Returns the server's representation of the backup, and an error, if there is any. + Create(ctx context.Context, backup *v1.Backup, opts metav1.CreateOptions) (*v1.Backup, error) + + // Update takes the representation of a backup and updates it. Returns the server's representation of the backup, and an error, if there is any. + Update(ctx context.Context, backup *v1.Backup, opts metav1.UpdateOptions) (*v1.Backup, error) + + // UpdateStatus was generated because the type contains a Status member. + UpdateStatus(ctx context.Context, backup *v1.Backup, opts metav1.UpdateOptions) (*v1.Backup, error) + + // UpdateStatusInProgress sets the status of the backup to "in progress". + UpdateStatusInProgress(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) + + // UpdateStatusCompleted sets the status of the backup to "completed". + UpdateStatusCompleted(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) + + // UpdateStatusDeleting sets the status of the backup to "deleting". + UpdateStatusDeleting(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) + + // Delete takes name of the backup and deletes it. Returns an error if one occurs. + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + + // DeleteCollection deletes a collection of objects. + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + + // Get takes name of the backup, and returns the corresponding backup object, and an error if there is any. + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Backup, error) + + // List takes label and field selectors, and returns the list of Backups that match those selectors. + List(ctx context.Context, opts metav1.ListOptions) (*v1.BackupList, error) + + // Watch returns a watch.Interface that watches the requested backups. + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + + // Patch applies the patch and returns the patched backup. + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Backup, err error) + + // AddFinalizer adds the given finalizer to the backup. + AddFinalizer(ctx context.Context, backup *v1.Backup, finalizer string) (*v1.Backup, error) + + // RemoveFinalizer removes the given finalizer to the backup. + RemoveFinalizer(ctx context.Context, backup *v1.Backup, finalizer string) (*v1.Backup, error) +} + +type backupClient struct { + client rest.Interface + ns string +} + +// UpdateStatusInProgress sets the status of the backup to "in progress". +func (d *backupClient) UpdateStatusInProgress(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) { + return d.updateStatusWithRetry(ctx, backup, v1.BackupStatusInProgress) +} + +// UpdateStatusCompleted sets the status of the backup to "completed". +func (d *backupClient) UpdateStatusCompleted(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) { + return d.updateStatusWithRetry(ctx, backup, v1.BackupStatusCompleted) +} + +// UpdateStatusDeleting sets the status of the backup to "deleting". +func (d *backupClient) UpdateStatusDeleting(ctx context.Context, backup *v1.Backup) (*v1.Backup, error) { + return d.updateStatusWithRetry(ctx, backup, v1.BackupStatusDeleting) +} + +func (d *backupClient) updateStatusWithRetry(ctx context.Context, backup *v1.Backup, targetStatus string) (*v1.Backup, error) { + var resultBackup *v1.Backup + err := retry.OnConflict(func() error { + updatedBackup, err := d.Get(ctx, backup.GetName(), metav1.GetOptions{}) + if err != nil { + return err + } + + // do not overwrite the whole status, so we do not lose other values from the Status object + // esp. a potentially set requeue time + updatedBackup.Status.Status = targetStatus + resultBackup, err = d.UpdateStatus(ctx, updatedBackup, metav1.UpdateOptions{}) + return err + }) + + return resultBackup, err +} + +// AddFinalizer adds the given finalizer to the backup. +func (d *backupClient) AddFinalizer(ctx context.Context, backup *v1.Backup, finalizer string) (*v1.Backup, error) { + controllerutil.AddFinalizer(backup, finalizer) + result, err := d.Update(ctx, backup, metav1.UpdateOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to add finalizer %s to backup: %w", finalizer, err) + } + + return result, nil +} + +// RemoveFinalizer removes the given finalizer to the backup. +func (d *backupClient) RemoveFinalizer(ctx context.Context, backup *v1.Backup, finalizer string) (*v1.Backup, error) { + controllerutil.RemoveFinalizer(backup, finalizer) + result, err := d.Update(ctx, backup, metav1.UpdateOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to remove finalizer %s from backup: %w", finalizer, err) + } + + return result, err +} + +// Get takes name of the backup, and returns the corresponding backup object, and an error if there is any. +func (d *backupClient) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Backup, err error) { + result = &v1.Backup{} + err = d.client.Get(). + Namespace(d.ns). + Resource("backups"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Backups that match those selectors. +func (d *backupClient) List(ctx context.Context, opts metav1.ListOptions) (result *v1.BackupList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.BackupList{} + err = d.client.Get(). + Namespace(d.ns). + Resource("backups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested backups. +func (d *backupClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return d.client.Get(). + Namespace(d.ns). + Resource("backups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a backup and creates it. Returns the server's representation of the backup, and an error, if there is any. +func (d *backupClient) Create(ctx context.Context, backup *v1.Backup, opts metav1.CreateOptions) (result *v1.Backup, err error) { + result = &v1.Backup{} + err = d.client.Post(). + Namespace(d.ns). + Resource("backups"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backup). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a backup and updates it. Returns the server's representation of the backup, and an error, if there is any. +func (d *backupClient) Update(ctx context.Context, backup *v1.Backup, opts metav1.UpdateOptions) (result *v1.Backup, err error) { + result = &v1.Backup{} + err = d.client.Put(). + Namespace(d.ns). + Resource("backups"). + Name(backup.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backup). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (d *backupClient) UpdateStatus(ctx context.Context, backup *v1.Backup, opts metav1.UpdateOptions) (result *v1.Backup, err error) { + result = &v1.Backup{} + err = d.client.Put(). + Namespace(d.ns). + Resource("backups"). + Name(backup.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(backup). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the backup and deletes it. Returns an error if one occurs. +func (d *backupClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return d.client.Delete(). + Namespace(d.ns). + Resource("backups"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (d *backupClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return d.client.Delete(). + Namespace(d.ns). + Resource("backups"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched backup. +func (d *backupClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Backup, err error) { + result = &v1.Backup{} + err = d.client.Patch(pt). + Namespace(d.ns). + Resource("backups"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/api/ecosystem/ecosystemClientSet.go b/pkg/api/ecosystem/ecosystemClientSet.go new file mode 100644 index 0000000..c47904a --- /dev/null +++ b/pkg/api/ecosystem/ecosystemClientSet.go @@ -0,0 +1,94 @@ +package ecosystem + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" +) + +type Interface interface { + kubernetes.Interface + EcosystemV1Alpha1() V1Alpha1Interface +} + +type V1Alpha1Interface interface { + BackupsGetter + RestoresGetter +} + +type BackupsGetter interface { + Backups(namespace string) BackupInterface +} + +type RestoresGetter interface { + Restores(namespace string) RestoreInterface +} + +// NewClientSet creates a new instance of the client set for this operator. +func NewClientSet(config *rest.Config, clientSet *kubernetes.Clientset) (*ClientSet, error) { + backupRestoreClient, err := NewForConfig(config) + if err != nil { + return nil, err + } + + return &ClientSet{ + Interface: clientSet, + ecosystemV1Alpha1: backupRestoreClient, + }, nil +} + +type ClientSet struct { + kubernetes.Interface + ecosystemV1Alpha1 V1Alpha1Interface +} + +func (cs *ClientSet) EcosystemV1Alpha1() V1Alpha1Interface { + return cs.ecosystemV1Alpha1 +} + +// NewForConfig creates a new V1Alpha1Client for a given rest.Config. +func NewForConfig(c *rest.Config) (*V1Alpha1Client, error) { + config := *c + gv := schema.GroupVersion{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version} + config.ContentConfig.GroupVersion = &gv + config.APIPath = "/apis" + + s := scheme.Scheme + err := v1.AddToScheme(s) + if err != nil { + return nil, err + } + + metav1.AddToGroupVersion(s, gv) + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + config.UserAgent = rest.DefaultKubernetesUserAgent() + + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + + return &V1Alpha1Client{restClient: client}, nil +} + +type V1Alpha1Client struct { + restClient rest.Interface +} + +func (brc *V1Alpha1Client) Backups(namespace string) BackupInterface { + return &backupClient{ + client: brc.restClient, + ns: namespace, + } +} + +func (brc *V1Alpha1Client) Restores(namespace string) RestoreInterface { + return &restoreClient{ + client: brc.restClient, + ns: namespace, + } +} diff --git a/pkg/api/ecosystem/restoreRestClient.go b/pkg/api/ecosystem/restoreRestClient.go new file mode 100644 index 0000000..8e101f5 --- /dev/null +++ b/pkg/api/ecosystem/restoreRestClient.go @@ -0,0 +1,251 @@ +package ecosystem + +import ( + "context" + "fmt" + "time" + + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + "github.com/cloudogu/k8s-backup-operator/pkg/retry" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +type RestoreInterface interface { + // Create takes the representation of a restore and creates it. Returns the server's representation of the restore, and an error, if there is any. + Create(ctx context.Context, restore *v1.Restore, opts metav1.CreateOptions) (*v1.Restore, error) + + // Update takes the representation of a restore and updates it. Returns the server's representation of the restore, and an error, if there is any. + Update(ctx context.Context, restore *v1.Restore, opts metav1.UpdateOptions) (*v1.Restore, error) + + // UpdateStatus was generated because the type contains a Status member. + UpdateStatus(ctx context.Context, restore *v1.Restore, opts metav1.UpdateOptions) (*v1.Restore, error) + + // UpdateStatusInProgress sets the status of the restore to "in progress". + UpdateStatusInProgress(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) + + // UpdateStatusCompleted sets the status of the restore to "completed". + UpdateStatusCompleted(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) + + // UpdateStatusDeleting sets the status of the restore to "deleting". + UpdateStatusDeleting(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) + + // Delete takes name of the restore and deletes it. Returns an error if one occurs. + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + + // DeleteCollection deletes a collection of objects. + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + + // Get takes name of the restore, and returns the corresponding restore object, and an error if there is any. + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Restore, error) + + // List takes label and field selectors, and returns the list of Restores that match those selectors. + List(ctx context.Context, opts metav1.ListOptions) (*v1.RestoreList, error) + + // Watch returns a watch.Interface that watches the requested restores. + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + + // Patch applies the patch and returns the patched restore. + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Restore, err error) + + // AddFinalizer adds the given finalizer to the restore. + AddFinalizer(ctx context.Context, restore *v1.Restore, finalizer string) (*v1.Restore, error) + + // RemoveFinalizer removes the given finalizer to the restore. + RemoveFinalizer(ctx context.Context, restore *v1.Restore, finalizer string) (*v1.Restore, error) +} + +type restoreClient struct { + client rest.Interface + ns string +} + +// UpdateStatusInProgress sets the status of the restore to "in progress". +func (d *restoreClient) UpdateStatusInProgress(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) { + return d.updateStatusWithRetry(ctx, restore, v1.RestoreStatusInProgress) +} + +// UpdateStatusCompleted sets the status of the restore to "completed". +func (d *restoreClient) UpdateStatusCompleted(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) { + return d.updateStatusWithRetry(ctx, restore, v1.RestoreStatusCompleted) +} + +// UpdateStatusDeleting sets the status of the restore to "deleting". +func (d *restoreClient) UpdateStatusDeleting(ctx context.Context, restore *v1.Restore) (*v1.Restore, error) { + return d.updateStatusWithRetry(ctx, restore, v1.RestoreStatusDeleting) +} + +func (d *restoreClient) updateStatusWithRetry(ctx context.Context, restore *v1.Restore, targetStatus string) (*v1.Restore, error) { + var resultRestore *v1.Restore + err := retry.OnConflict(func() error { + updatedRestore, err := d.Get(ctx, restore.GetName(), metav1.GetOptions{}) + if err != nil { + return err + } + + // do not overwrite the whole status, so we do not lose other values from the Status object + // esp. a potentially set requeue time + updatedRestore.Status.Status = targetStatus + resultRestore, err = d.UpdateStatus(ctx, updatedRestore, metav1.UpdateOptions{}) + return err + }) + + return resultRestore, err +} + +// AddFinalizer adds the given finalizer to the restore. +func (d *restoreClient) AddFinalizer(ctx context.Context, restore *v1.Restore, finalizer string) (*v1.Restore, error) { + controllerutil.AddFinalizer(restore, finalizer) + result, err := d.Update(ctx, restore, metav1.UpdateOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to add finalizer %s to restore: %w", finalizer, err) + } + + return result, nil +} + +// RemoveFinalizer removes the given finalizer to the restore. +func (d *restoreClient) RemoveFinalizer(ctx context.Context, restore *v1.Restore, finalizer string) (*v1.Restore, error) { + controllerutil.RemoveFinalizer(restore, finalizer) + result, err := d.Update(ctx, restore, metav1.UpdateOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to remove finalizer %s from restore: %w", finalizer, err) + } + + return result, err +} + +// Get takes name of the restore, and returns the corresponding restore object, and an error if there is any. +func (d *restoreClient) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.Restore, err error) { + result = &v1.Restore{} + err = d.client.Get(). + Namespace(d.ns). + Resource("restores"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Restores that match those selectors. +func (d *restoreClient) List(ctx context.Context, opts metav1.ListOptions) (result *v1.RestoreList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.RestoreList{} + err = d.client.Get(). + Namespace(d.ns). + Resource("restores"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested restores. +func (d *restoreClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return d.client.Get(). + Namespace(d.ns). + Resource("restores"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a restore and creates it. Returns the server's representation of the restore, and an error, if there is any. +func (d *restoreClient) Create(ctx context.Context, restore *v1.Restore, opts metav1.CreateOptions) (result *v1.Restore, err error) { + result = &v1.Restore{} + err = d.client.Post(). + Namespace(d.ns). + Resource("restores"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(restore). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a restore and updates it. Returns the server's representation of the restore, and an error, if there is any. +func (d *restoreClient) Update(ctx context.Context, restore *v1.Restore, opts metav1.UpdateOptions) (result *v1.Restore, err error) { + result = &v1.Restore{} + err = d.client.Put(). + Namespace(d.ns). + Resource("restores"). + Name(restore.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(restore). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (d *restoreClient) UpdateStatus(ctx context.Context, restore *v1.Restore, opts metav1.UpdateOptions) (result *v1.Restore, err error) { + result = &v1.Restore{} + err = d.client.Put(). + Namespace(d.ns). + Resource("restores"). + Name(restore.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(restore). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the restore and deletes it. Returns an error if one occurs. +func (d *restoreClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return d.client.Delete(). + Namespace(d.ns). + Resource("restores"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (d *restoreClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return d.client.Delete(). + Namespace(d.ns). + Resource("restores"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched restore. +func (d *restoreClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Restore, err error) { + result = &v1.Restore{} + err = d.client.Patch(pt). + Namespace(d.ns). + Resource("restores"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/api/v1/backup_types.go b/pkg/api/v1/backup_types.go new file mode 100644 index 0000000..4d57f38 --- /dev/null +++ b/pkg/api/v1/backup_types.go @@ -0,0 +1,53 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + BackupStatusNew = "" + BackupStatusInProgress = "in progress" + BackupStatusCompleted = "completed" + BackupStatusDeleting = "deleting" +) + +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// BackupSpec defines the desired state of Backup +type BackupSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of Backup. Edit backup_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// BackupStatus defines the observed state of Backup +type BackupStatus struct { + Status string `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// Backup is the Schema for the backups API +type Backup struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BackupSpec `json:"spec,omitempty"` + Status BackupStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// BackupList contains a list of Backup +type BackupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Backup `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Backup{}, &BackupList{}) +} diff --git a/pkg/api/v1/groupversion_info.go b/pkg/api/v1/groupversion_info.go new file mode 100644 index 0000000..d47ae91 --- /dev/null +++ b/pkg/api/v1/groupversion_info.go @@ -0,0 +1,20 @@ +// Package v1 contains API Schema definitions for the k8s v1 API group +// +kubebuilder:object:generate=true +// +groupName=k8s.cloudogu.com +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "k8s.cloudogu.com", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/pkg/api/v1/restore_types.go b/pkg/api/v1/restore_types.go new file mode 100644 index 0000000..92228bc --- /dev/null +++ b/pkg/api/v1/restore_types.go @@ -0,0 +1,53 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + RestoreStatusNew = "" + RestoreStatusInProgress = "in progress" + RestoreStatusCompleted = "completed" + RestoreStatusDeleting = "deleting" +) + +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// RestoreSpec defines the desired state of Restore +type RestoreSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Foo is an example field of Restore. Edit restore_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// RestoreStatus defines the observed state of Restore +type RestoreStatus struct { + Status string `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// Restore is the Schema for the restores API +type Restore struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RestoreSpec `json:"spec,omitempty"` + Status RestoreStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RestoreList contains a list of Restore +type RestoreList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Restore `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Restore{}, &RestoreList{}) +} diff --git a/pkg/api/v1/zz_generated.deepcopy.go b/pkg/api/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000..f9afe9b --- /dev/null +++ b/pkg/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,192 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +This file was generated with "make generate". +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backup) DeepCopyInto(out *Backup) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. +func (in *Backup) DeepCopy() *Backup { + if in == nil { + return nil + } + out := new(Backup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Backup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupList) DeepCopyInto(out *BackupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Backup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupList. +func (in *BackupList) DeepCopy() *BackupList { + if in == nil { + return nil + } + out := new(BackupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupSpec) DeepCopyInto(out *BackupSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupSpec. +func (in *BackupSpec) DeepCopy() *BackupSpec { + if in == nil { + return nil + } + out := new(BackupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupStatus) DeepCopyInto(out *BackupStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupStatus. +func (in *BackupStatus) DeepCopy() *BackupStatus { + if in == nil { + return nil + } + out := new(BackupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Restore) DeepCopyInto(out *Restore) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Restore. +func (in *Restore) DeepCopy() *Restore { + if in == nil { + return nil + } + out := new(Restore) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Restore) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestoreList) DeepCopyInto(out *RestoreList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Restore, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreList. +func (in *RestoreList) DeepCopy() *RestoreList { + if in == nil { + return nil + } + out := new(RestoreList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RestoreList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestoreSpec) DeepCopyInto(out *RestoreSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreSpec. +func (in *RestoreSpec) DeepCopy() *RestoreSpec { + if in == nil { + return nil + } + out := new(RestoreSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestoreStatus) DeepCopyInto(out *RestoreStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreStatus. +func (in *RestoreStatus) DeepCopy() *RestoreStatus { + if in == nil { + return nil + } + out := new(RestoreStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 0a87bf0..0908eec 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -2,68 +2,73 @@ package config import ( "fmt" - "github.com/cloudogu/cesapp-lib/core" "os" + + "github.com/Masterminds/semver/v3" ctrl "sigs.k8s.io/controller-runtime" ) const ( - StageDevelopment = "development" - StageProduction = "production" - StageEnvironmentVariable = "STAGE" + StageDevelopment = "development" + StageProduction = "production" + stageEnvVar = "STAGE" + namespaceEnvVar = "NAMESPACE" ) -const cacheDir = "/tmp/dogu-registry-cache" - -var Stage = StageProduction - -var ( - envVarNamespace = "NAMESPACE" - log = ctrl.Log.WithName("config") -) +var log = ctrl.Log.WithName("config") // OperatorConfig contains all configurable values for the dogu operator. type OperatorConfig struct { - // Namespace specifies the namespace that the operator is deployed to. - Namespace string `json:"namespace"` // Version contains the current version of the operator - Version *core.Version `json:"version"` + Version *semver.Version + // Namespace specifies the namespace that the operator is deployed to. + Namespace string +} + +var Stage = StageProduction + +func IsStageDevelopment() bool { + return Stage == StageDevelopment } // NewOperatorConfig creates a new operator config by reading values from the environment variables func NewOperatorConfig(version string) (*OperatorConfig, error) { - stage, err := getEnvVar(StageEnvironmentVariable) - if err != nil { - log.Error(err, "Error reading stage environment variable. Use Stage production") - } - Stage = stage - - if Stage == StageDevelopment { - log.Info("Starting in development mode! This is not recommended for production!") - } + configureStage() - parsedVersion, err := core.ParseVersion(version) + parsedVersion, err := semver.NewVersion(version) if err != nil { return nil, fmt.Errorf("failed to parse version: %w", err) } log.Info(fmt.Sprintf("Version: [%s]", version)) - namespace, err := readNamespace() + namespace, err := getNamespace() if err != nil { return nil, fmt.Errorf("failed to read namespace: %w", err) } log.Info(fmt.Sprintf("Deploying the k8s dogu operator in namespace %s", namespace)) return &OperatorConfig{ + Version: parsedVersion, Namespace: namespace, - Version: &parsedVersion, }, nil } -func readNamespace() (string, error) { - namespace, err := getEnvVar(envVarNamespace) +func configureStage() { + var err error + Stage, err = getEnvVar(stageEnvVar) + if err != nil { + log.Error(err, "Error reading stage environment variable. Use stage production") + } + + if IsStageDevelopment() { + log.Info("Starting in development mode! This is not recommended for production!") + } +} + +func getNamespace() (string, error) { + namespace, err := getEnvVar(namespaceEnvVar) if err != nil { - return "", fmt.Errorf("failed to get env var [%s]: %w", envVarNamespace, err) + return "", fmt.Errorf("failed to get env var [%s]: %w", namespaceEnvVar, err) } return namespace, nil diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go deleted file mode 100644 index 84369c4..0000000 --- a/pkg/config/config_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package config - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewOperatorConfig(t *testing.T) { - _ = os.Unsetenv("NAMESPACE") - - expectedNamespace := "myNamespace" - - t.Run("Error on missing namespace env var", func(t *testing.T) { - // when - operatorConfig, err := NewOperatorConfig("0.0.0") - - // then - require.Error(t, err) - assert.ErrorContains(t, err, "failed to get env var [NAMESPACE]: environment variable NAMESPACE must be set") - assert.Nil(t, operatorConfig) - }) - t.Setenv("NAMESPACE", expectedNamespace) - t.Run("Create config successfully", func(t *testing.T) { - // when - operatorConfig, err := NewOperatorConfig("0.1.0") - - // then - require.NoError(t, err) - require.NotNil(t, operatorConfig) - assert.Equal(t, expectedNamespace, operatorConfig.Namespace) - assert.Equal(t, "0.1.0", operatorConfig.Version.Raw) - }) -} diff --git a/pkg/controllers/backupController.go b/pkg/controllers/backupController.go deleted file mode 100644 index 8bb2fab..0000000 --- a/pkg/controllers/backupController.go +++ /dev/null @@ -1,40 +0,0 @@ -package controllers - -import ( - "context" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/tools/record" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -// backupReconciler watches every Service object in the cluster and creates ingress objects accordingly. -type backupReconciler struct { - client client.Client - recorder record.EventRecorder -} - -// NewBackupReconciler creates a new backup reconciler. -func NewBackupReconciler(client client.Client, recorder record.EventRecorder) *backupReconciler { - return &backupReconciler{ - client: client, - recorder: recorder, - } -} - -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -func (r *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - logger.Info("Reconcile this backup manager") - - return ctrl.Result{}, nil -} - -// SetupWithManager sets up the controller with the Manager. -func (r *backupReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&corev1.Service{}). - Complete(r) -} diff --git a/pkg/controllers/backupReconciler.go b/pkg/controllers/backupReconciler.go new file mode 100644 index 0000000..4ace1e1 --- /dev/null +++ b/pkg/controllers/backupReconciler.go @@ -0,0 +1,49 @@ +package controller + +import ( + "context" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" + + k8sv1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" +) + +func NewBackupReconciler(clientSet ecosystemInterface, recorder eventRecorder, namespace string) *backupReconciler { + return &backupReconciler{clientSet: clientSet, recorder: recorder, namespace: namespace} +} + +// backupReconciler reconciles a Backup object +type backupReconciler struct { + clientSet ecosystemInterface + recorder eventRecorder + namespace string +} + +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=backups,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=backups/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=backups/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Backup object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.15.0/pkg/reconcile +func (r *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *backupReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&k8sv1.Backup{}). + Complete(r) +} diff --git a/pkg/controllers/interfaces.go b/pkg/controllers/interfaces.go new file mode 100644 index 0000000..779f89a --- /dev/null +++ b/pkg/controllers/interfaces.go @@ -0,0 +1,15 @@ +package controller + +import ( + "k8s.io/client-go/tools/record" + + "github.com/cloudogu/k8s-backup-operator/pkg/api/ecosystem" +) + +type ecosystemInterface interface { + ecosystem.Interface +} + +type eventRecorder interface { + record.EventRecorder +} diff --git a/pkg/controllers/restoreReconciler.go b/pkg/controllers/restoreReconciler.go new file mode 100644 index 0000000..50b3a2f --- /dev/null +++ b/pkg/controllers/restoreReconciler.go @@ -0,0 +1,48 @@ +package controller + +import ( + "context" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" + + k8sv1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" +) + +func NewRestoreReconciler(clientSet ecosystemInterface, recorder eventRecorder, namespace string) *restoreReconciler { + return &restoreReconciler{clientSet: clientSet, recorder: recorder, namespace: namespace} +} + +// restoreReconciler reconciles a Restore object +type restoreReconciler struct { + clientSet ecosystemInterface + recorder eventRecorder + namespace string +} + +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=restores,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=restores/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=k8s.cloudogu.com,resources=restores/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Restore object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.15.0/pkg/reconcile +func (r *restoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *restoreReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&k8sv1.Restore{}). + Complete(r) +} diff --git a/pkg/controllers/suite_int_test.go b/pkg/controllers/suite_int_test.go new file mode 100644 index 0000000..a07d79e --- /dev/null +++ b/pkg/controllers/suite_int_test.go @@ -0,0 +1,64 @@ +//go:build k8s_integration +// +build k8s_integration + +package controller + +import ( + "path/filepath" + "testing" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + k8sv1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestControllers(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = k8sv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go deleted file mode 100644 index db44a7c..0000000 --- a/pkg/logging/logger.go +++ /dev/null @@ -1,118 +0,0 @@ -package logging - -import ( - "fmt" - "os" - "strings" - - "github.com/bombsimon/logrusr/v2" - "github.com/cloudogu/cesapp-lib/core" - "github.com/cloudogu/k8s-apply-lib/apply" - "github.com/go-logr/logr" - "github.com/sirupsen/logrus" - ctrl "sigs.k8s.io/controller-runtime" -) - -const logLevelEnvVar = "LOG_LEVEL" - -const ( - errorLevel int = iota - warningLevel - infoLevel - debugLevel -) - -var CurrentLogLevel = logrus.ErrorLevel - -type libraryLogger struct { - logger logr.LogSink - name string -} - -func (ll *libraryLogger) log(level int, args ...interface{}) { - ll.logger.Info(level, fmt.Sprintf("[%s] %s", ll.name, fmt.Sprint(args...))) -} - -func (ll *libraryLogger) logf(level int, format string, args ...interface{}) { - ll.logger.Info(level, fmt.Sprintf("[%s] %s", ll.name, fmt.Sprintf(format, args...))) -} - -func (ll *libraryLogger) Debug(args ...interface{}) { - ll.log(debugLevel, args...) -} - -func (ll *libraryLogger) Info(args ...interface{}) { - ll.log(infoLevel, args...) -} - -func (ll *libraryLogger) Warning(args ...interface{}) { - ll.log(warningLevel, args...) -} - -func (ll *libraryLogger) Error(args ...interface{}) { - ll.log(errorLevel, args...) -} - -func (ll *libraryLogger) Debugf(format string, args ...interface{}) { - ll.logf(debugLevel, format, args...) -} - -func (ll *libraryLogger) Infof(format string, args ...interface{}) { - ll.logf(infoLevel, format, args...) -} - -func (ll *libraryLogger) Warningf(format string, args ...interface{}) { - ll.logf(warningLevel, format, args...) -} - -func (ll *libraryLogger) Errorf(format string, args ...interface{}) { - ll.logf(errorLevel, format, args...) -} - -func getLogLevelFromEnv() (logrus.Level, error) { - logLevel, found := os.LookupEnv(logLevelEnvVar) - if !found || strings.TrimSpace(logLevel) == "" { - return logrus.ErrorLevel, nil - } - - level, err := logrus.ParseLevel(logLevel) - if err != nil { - return logrus.ErrorLevel, fmt.Errorf("value of log environment variable [%s] is not a valid log level: %w", logLevelEnvVar, err) - } - - return level, nil -} - -func ConfigureLogger() error { - level, err := getLogLevelFromEnv() - if err != nil { - return err - } - - // create logrus logger that can be styled and formatted - logrusLog := logrus.New() - logrusLog.SetFormatter(&logrus.TextFormatter{}) - logrusLog.SetLevel(level) - - CurrentLogLevel = level - - // convert logrus logger to logr logger - logrusLogrLogger := logrusr.New(logrusLog) - - // set logr logger as controller logger - ctrl.SetLogger(logrusLogrLogger) - - // set custom logger implementation to cesapp-lib logger - cesappLibLogger := libraryLogger{name: "cesapp-lib", logger: logrusLogrLogger.GetSink()} - core.GetLogger = func() core.Logger { - return &cesappLibLogger - } - - // set custom logger implementation to k8s-apply-lib logger - k8sApplyLibLogger := libraryLogger{name: "k8s-apply-lib", logger: logrusLogrLogger.GetSink()} - apply.GetLogger = func() apply.Logger { - return &k8sApplyLibLogger - } - - return nil -} diff --git a/pkg/logging/logger_test.go b/pkg/logging/logger_test.go deleted file mode 100644 index 03d154d..0000000 --- a/pkg/logging/logger_test.go +++ /dev/null @@ -1,179 +0,0 @@ -package logging - -import ( - "github.com/cloudogu/k8s-backup-operator/pkg/mocks/external" - "os" - "testing" - - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/cloudogu/cesapp-lib/core" -) - -func TestConfigureLogger(t *testing.T) { - originalControllerLogger := ctrl.Log - originalLibraryLogger := core.GetLogger() - defer func() { - ctrl.Log = originalControllerLogger - core.GetLogger = func() core.Logger { - return originalLibraryLogger - } - }() - - t.Run("create logger with no log level set in env -> should use default", func(t *testing.T) { - // given - _ = os.Unsetenv(logLevelEnvVar) - - // when - err := ConfigureLogger() - - // then - assert.NoError(t, err) - }) - t.Run("should not fail with empty string log level and return error level", func(t *testing.T) { - // given - t.Setenv(logLevelEnvVar, "") - - // when - err := ConfigureLogger() - - // then - assert.NoError(t, err) - assert.Equal(t, logrus.ErrorLevel, CurrentLogLevel) - }) - - t.Run("create logger with log level INFO", func(t *testing.T) { - // given - _ = os.Setenv(logLevelEnvVar, "INFO") - - // when - err := ConfigureLogger() - - // then - core.GetLogger().Info("test") - assert.NoError(t, err) - }) - - t.Run("create logger with invalid log level TEST_LEVEL", func(t *testing.T) { - // given - _ = os.Setenv(logLevelEnvVar, "TEST_LEVEL") - - // when - err := ConfigureLogger() - - // then - assert.Error(t, err) - assert.ErrorContains(t, err, "value of log environment variable [LOG_LEVEL] is not a valid log level") - }) -} - -func Test_libraryLogger_Debug(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", debugLevel, "[testLogger] test debug call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - logger.Debug("test debug call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Debugf(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", debugLevel, "[testLogger] myText - test debug call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - text := "myText" - logger.Debugf("%s - %s", text, "test debug call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Error(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", errorLevel, "[testLogger] test error call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - logger.Error("test error call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Errorf(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", errorLevel, "[testLogger] myText - test error call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - text := "myText" - logger.Errorf("%s - %s", text, "test error call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Info(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", infoLevel, "[testLogger] test info call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - logger.Info("test info call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Infof(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", infoLevel, "[testLogger] myText - test info call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - text := "myText" - logger.Infof("%s - %s", text, "test info call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Warning(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", warningLevel, "[testLogger] test warning call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - logger.Warning("test warning call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} - -func Test_libraryLogger_Warningf(t *testing.T) { - // given - loggerSink := &external.LogSink{} - loggerSink.On("Info", warningLevel, "[testLogger] myText - test warning call") - logger := libraryLogger{name: "testLogger", logger: loggerSink} - - // when - text := "myText" - logger.Warningf("%s - %s", text, "test warning call") - - // then - mock.AssertExpectationsForObjects(t, loggerSink) -} diff --git a/pkg/mocks/external/Client.go b/pkg/mocks/external/Client.go deleted file mode 100644 index 15506f8..0000000 --- a/pkg/mocks/external/Client.go +++ /dev/null @@ -1,225 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package external - -import ( - context "context" - - client "sigs.k8s.io/controller-runtime/pkg/client" - - meta "k8s.io/apimachinery/pkg/api/meta" - - mock "github.com/stretchr/testify/mock" - - runtime "k8s.io/apimachinery/pkg/runtime" - - types "k8s.io/apimachinery/pkg/types" -) - -// Client is an autogenerated mock type for the Client type -type Client struct { - mock.Mock -} - -// Create provides a mock function with given fields: ctx, obj, opts -func (_m *Client) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.CreateOption) error); ok { - r0 = rf(ctx, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Delete provides a mock function with given fields: ctx, obj, opts -func (_m *Client) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteOption) error); ok { - r0 = rf(ctx, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// DeleteAllOf provides a mock function with given fields: ctx, obj, opts -func (_m *Client) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteAllOfOption) error); ok { - r0 = rf(ctx, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Get provides a mock function with given fields: ctx, key, obj -func (_m *Client) Get(ctx context.Context, key types.NamespacedName, obj client.Object) error { - ret := _m.Called(ctx, key, obj) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.NamespacedName, client.Object) error); ok { - r0 = rf(ctx, key, obj) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// List provides a mock function with given fields: ctx, list, opts -func (_m *Client) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, list) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.ObjectList, ...client.ListOption) error); ok { - r0 = rf(ctx, list, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Patch provides a mock function with given fields: ctx, obj, patch, opts -func (_m *Client) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj, patch) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, client.Patch, ...client.PatchOption) error); ok { - r0 = rf(ctx, obj, patch, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RESTMapper provides a mock function with given fields: -func (_m *Client) RESTMapper() meta.RESTMapper { - ret := _m.Called() - - var r0 meta.RESTMapper - if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(meta.RESTMapper) - } - } - - return r0 -} - -// Scheme provides a mock function with given fields: -func (_m *Client) Scheme() *runtime.Scheme { - ret := _m.Called() - - var r0 *runtime.Scheme - if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*runtime.Scheme) - } - } - - return r0 -} - -// Status provides a mock function with given fields: -func (_m *Client) Status() client.StatusWriter { - ret := _m.Called() - - var r0 client.StatusWriter - if rf, ok := ret.Get(0).(func() client.StatusWriter); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(client.StatusWriter) - } - } - - return r0 -} - -// Update provides a mock function with given fields: ctx, obj, opts -func (_m *Client) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.UpdateOption) error); ok { - r0 = rf(ctx, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTNewClient interface { - mock.TestingT - Cleanup(func()) -} - -// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { - mock := &Client{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/mocks/external/EventRecorder.go b/pkg/mocks/external/EventRecorder.go deleted file mode 100644 index dfdab1c..0000000 --- a/pkg/mocks/external/EventRecorder.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package external - -import ( - mock "github.com/stretchr/testify/mock" - - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// EventRecorder is an autogenerated mock type for the EventRecorder type -type EventRecorder struct { - mock.Mock -} - -// AnnotatedEventf provides a mock function with given fields: object, annotations, eventtype, reason, messageFmt, args -func (_m *EventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{}) { - var _ca []interface{} - _ca = append(_ca, object, annotations, eventtype, reason, messageFmt) - _ca = append(_ca, args...) - _m.Called(_ca...) -} - -// Event provides a mock function with given fields: object, eventtype, reason, message -func (_m *EventRecorder) Event(object runtime.Object, eventtype string, reason string, message string) { - _m.Called(object, eventtype, reason, message) -} - -// Eventf provides a mock function with given fields: object, eventtype, reason, messageFmt, args -func (_m *EventRecorder) Eventf(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{}) { - var _ca []interface{} - _ca = append(_ca, object, eventtype, reason, messageFmt) - _ca = append(_ca, args...) - _m.Called(_ca...) -} - -type mockConstructorTestingTNewEventRecorder interface { - mock.TestingT - Cleanup(func()) -} - -// NewEventRecorder creates a new instance of EventRecorder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewEventRecorder(t mockConstructorTestingTNewEventRecorder) *EventRecorder { - mock := &EventRecorder{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/mocks/external/LogSink.go b/pkg/mocks/external/LogSink.go deleted file mode 100644 index a2dd1cd..0000000 --- a/pkg/mocks/external/LogSink.go +++ /dev/null @@ -1,97 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package external - -import ( - logr "github.com/go-logr/logr" - mock "github.com/stretchr/testify/mock" -) - -// LogSink is an autogenerated mock type for the LogSink type -type LogSink struct { - mock.Mock -} - -// Enabled provides a mock function with given fields: level -func (_m *LogSink) Enabled(level int) bool { - ret := _m.Called(level) - - var r0 bool - if rf, ok := ret.Get(0).(func(int) bool); ok { - r0 = rf(level) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Error provides a mock function with given fields: err, msg, keysAndValues -func (_m *LogSink) Error(err error, msg string, keysAndValues ...interface{}) { - var _ca []interface{} - _ca = append(_ca, err, msg) - _ca = append(_ca, keysAndValues...) - _m.Called(_ca...) -} - -// Info provides a mock function with given fields: level, msg, keysAndValues -func (_m *LogSink) Info(level int, msg string, keysAndValues ...interface{}) { - var _ca []interface{} - _ca = append(_ca, level, msg) - _ca = append(_ca, keysAndValues...) - _m.Called(_ca...) -} - -// Init provides a mock function with given fields: info -func (_m *LogSink) Init(info logr.RuntimeInfo) { - _m.Called(info) -} - -// WithName provides a mock function with given fields: name -func (_m *LogSink) WithName(name string) logr.LogSink { - ret := _m.Called(name) - - var r0 logr.LogSink - if rf, ok := ret.Get(0).(func(string) logr.LogSink); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(logr.LogSink) - } - } - - return r0 -} - -// WithValues provides a mock function with given fields: keysAndValues -func (_m *LogSink) WithValues(keysAndValues ...interface{}) logr.LogSink { - var _ca []interface{} - _ca = append(_ca, keysAndValues...) - ret := _m.Called(_ca...) - - var r0 logr.LogSink - if rf, ok := ret.Get(0).(func(...interface{}) logr.LogSink); ok { - r0 = rf(keysAndValues...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(logr.LogSink) - } - } - - return r0 -} - -type mockConstructorTestingTNewLogSink interface { - mock.TestingT - Cleanup(func()) -} - -// NewLogSink creates a new instance of LogSink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewLogSink(t mockConstructorTestingTNewLogSink) *LogSink { - mock := &LogSink{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/mocks/external/Manager.go b/pkg/mocks/external/Manager.go deleted file mode 100644 index 5606ea5..0000000 --- a/pkg/mocks/external/Manager.go +++ /dev/null @@ -1,324 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package external - -import ( - cache "sigs.k8s.io/controller-runtime/pkg/cache" - client "sigs.k8s.io/controller-runtime/pkg/client" - - context "context" - - healthz "sigs.k8s.io/controller-runtime/pkg/healthz" - - http "net/http" - - logr "github.com/go-logr/logr" - - manager "sigs.k8s.io/controller-runtime/pkg/manager" - - meta "k8s.io/apimachinery/pkg/api/meta" - - mock "github.com/stretchr/testify/mock" - - record "k8s.io/client-go/tools/record" - - rest "k8s.io/client-go/rest" - - runtime "k8s.io/apimachinery/pkg/runtime" - - v1alpha1 "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" - - webhook "sigs.k8s.io/controller-runtime/pkg/webhook" -) - -// Manager is an autogenerated mock type for the Manager type -type Manager struct { - mock.Mock -} - -// Add provides a mock function with given fields: _a0 -func (_m *Manager) Add(_a0 manager.Runnable) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(manager.Runnable) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// AddHealthzCheck provides a mock function with given fields: name, check -func (_m *Manager) AddHealthzCheck(name string, check healthz.Checker) error { - ret := _m.Called(name, check) - - var r0 error - if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { - r0 = rf(name, check) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// AddMetricsExtraHandler provides a mock function with given fields: path, handler -func (_m *Manager) AddMetricsExtraHandler(path string, handler http.Handler) error { - ret := _m.Called(path, handler) - - var r0 error - if rf, ok := ret.Get(0).(func(string, http.Handler) error); ok { - r0 = rf(path, handler) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// AddReadyzCheck provides a mock function with given fields: name, check -func (_m *Manager) AddReadyzCheck(name string, check healthz.Checker) error { - ret := _m.Called(name, check) - - var r0 error - if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { - r0 = rf(name, check) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Elected provides a mock function with given fields: -func (_m *Manager) Elected() <-chan struct{} { - ret := _m.Called() - - var r0 <-chan struct{} - if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan struct{}) - } - } - - return r0 -} - -// GetAPIReader provides a mock function with given fields: -func (_m *Manager) GetAPIReader() client.Reader { - ret := _m.Called() - - var r0 client.Reader - if rf, ok := ret.Get(0).(func() client.Reader); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(client.Reader) - } - } - - return r0 -} - -// GetCache provides a mock function with given fields: -func (_m *Manager) GetCache() cache.Cache { - ret := _m.Called() - - var r0 cache.Cache - if rf, ok := ret.Get(0).(func() cache.Cache); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(cache.Cache) - } - } - - return r0 -} - -// GetClient provides a mock function with given fields: -func (_m *Manager) GetClient() client.Client { - ret := _m.Called() - - var r0 client.Client - if rf, ok := ret.Get(0).(func() client.Client); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(client.Client) - } - } - - return r0 -} - -// GetConfig provides a mock function with given fields: -func (_m *Manager) GetConfig() *rest.Config { - ret := _m.Called() - - var r0 *rest.Config - if rf, ok := ret.Get(0).(func() *rest.Config); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*rest.Config) - } - } - - return r0 -} - -// GetControllerOptions provides a mock function with given fields: -func (_m *Manager) GetControllerOptions() v1alpha1.ControllerConfigurationSpec { - ret := _m.Called() - - var r0 v1alpha1.ControllerConfigurationSpec - if rf, ok := ret.Get(0).(func() v1alpha1.ControllerConfigurationSpec); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(v1alpha1.ControllerConfigurationSpec) - } - - return r0 -} - -// GetEventRecorderFor provides a mock function with given fields: name -func (_m *Manager) GetEventRecorderFor(name string) record.EventRecorder { - ret := _m.Called(name) - - var r0 record.EventRecorder - if rf, ok := ret.Get(0).(func(string) record.EventRecorder); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(record.EventRecorder) - } - } - - return r0 -} - -// GetFieldIndexer provides a mock function with given fields: -func (_m *Manager) GetFieldIndexer() client.FieldIndexer { - ret := _m.Called() - - var r0 client.FieldIndexer - if rf, ok := ret.Get(0).(func() client.FieldIndexer); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(client.FieldIndexer) - } - } - - return r0 -} - -// GetLogger provides a mock function with given fields: -func (_m *Manager) GetLogger() logr.Logger { - ret := _m.Called() - - var r0 logr.Logger - if rf, ok := ret.Get(0).(func() logr.Logger); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(logr.Logger) - } - - return r0 -} - -// GetRESTMapper provides a mock function with given fields: -func (_m *Manager) GetRESTMapper() meta.RESTMapper { - ret := _m.Called() - - var r0 meta.RESTMapper - if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(meta.RESTMapper) - } - } - - return r0 -} - -// GetScheme provides a mock function with given fields: -func (_m *Manager) GetScheme() *runtime.Scheme { - ret := _m.Called() - - var r0 *runtime.Scheme - if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*runtime.Scheme) - } - } - - return r0 -} - -// GetWebhookServer provides a mock function with given fields: -func (_m *Manager) GetWebhookServer() *webhook.Server { - ret := _m.Called() - - var r0 *webhook.Server - if rf, ok := ret.Get(0).(func() *webhook.Server); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*webhook.Server) - } - } - - return r0 -} - -// SetFields provides a mock function with given fields: _a0 -func (_m *Manager) SetFields(_a0 interface{}) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(interface{}) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Start provides a mock function with given fields: ctx -func (_m *Manager) Start(ctx context.Context) error { - ret := _m.Called(ctx) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTNewManager interface { - mock.TestingT - Cleanup(func()) -} - -// NewManager creates a new instance of Manager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewManager(t mockConstructorTestingTNewManager) *Manager { - mock := &Manager{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/mocks/external/StatusWriter.go b/pkg/mocks/external/StatusWriter.go deleted file mode 100644 index afaf43d..0000000 --- a/pkg/mocks/external/StatusWriter.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package external - -import ( - context "context" - - client "sigs.k8s.io/controller-runtime/pkg/client" - - mock "github.com/stretchr/testify/mock" -) - -// StatusWriter is an autogenerated mock type for the StatusWriter type -type StatusWriter struct { - mock.Mock -} - -// Patch provides a mock function with given fields: ctx, obj, patch, opts -func (_m *StatusWriter) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj, patch) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, client.Patch, ...client.PatchOption) error); ok { - r0 = rf(ctx, obj, patch, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Update provides a mock function with given fields: ctx, obj, opts -func (_m *StatusWriter) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, obj) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.UpdateOption) error); ok { - r0 = rf(ctx, obj, opts...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTNewStatusWriter interface { - mock.TestingT - Cleanup(func()) -} - -// NewStatusWriter creates a new instance of StatusWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStatusWriter(t mockConstructorTestingTNewStatusWriter) *StatusWriter { - mock := &StatusWriter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/mocks/external/external.go b/pkg/mocks/external/external.go deleted file mode 100644 index e435ddf..0000000 --- a/pkg/mocks/external/external.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package external implements mocks that implement 3rd party interfaces, t. i. interfaces which we do not control. -// In order to avoid package dependency cycles these mock implementations reside in this package. -package external diff --git a/pkg/retry/retry.go b/pkg/retry/retry.go new file mode 100644 index 0000000..4108afd --- /dev/null +++ b/pkg/retry/retry.go @@ -0,0 +1,18 @@ +package retry + +import ( + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/retry" + "time" +) + +// OnConflict provides a K8s-way "retrier" mechanism to avoid conflicts on resource updates. +func OnConflict(fn func() error) error { + return retry.RetryOnConflict(wait.Backoff{ + Duration: 1500 * time.Millisecond, + Factor: 1.5, + Jitter: 0, + Steps: 9999, + Cap: 30 * time.Second, + }, fn) +} From 1b31c53f7f668388c45124807e60570b36da9223 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 10:15:39 +0200 Subject: [PATCH 03/37] #1 Update makefiles --- Makefile | 2 +- build/make/k8s-controller.mk | 2 +- build/make/k8s-dogu.tpl | 2 +- build/make/k8s-helm-temp-chart.yaml | 3 ++ build/make/k8s.mk | 79 ++++++++++++++++++++++++----- 5 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 build/make/k8s-helm-temp-chart.yaml diff --git a/Makefile b/Makefile index 880f7d2..fcf1998 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ VERSION=0.1.0 IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} GOTAG?=1.21 -MAKEFILES_VERSION=7.10.0 +MAKEFILES_VERSION=7.12.1 LINT_VERSION=v1.52.1 STAGE?=production diff --git a/build/make/k8s-controller.mk b/build/make/k8s-controller.mk index 5735f00..d7129ad 100644 --- a/build/make/k8s-controller.mk +++ b/build/make/k8s-controller.mk @@ -38,7 +38,7 @@ K8S_INTEGRATION_TEST_DIR=${TARGET_DIR}/k8s-integration-test ##@ K8s - EcoSystem .PHONY: build -build: image-import k8s-apply ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. +build: k8s-helm-apply ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. ##@ Release diff --git a/build/make/k8s-dogu.tpl b/build/make/k8s-dogu.tpl index 44cd9cf..296da65 100644 --- a/build/make/k8s-dogu.tpl +++ b/build/make/k8s-dogu.tpl @@ -3,7 +3,7 @@ kind: Dogu metadata: name: NAME labels: - dogu: NAME + app: ces spec: name: NAMESPACE/NAME version: VERSION \ No newline at end of file diff --git a/build/make/k8s-helm-temp-chart.yaml b/build/make/k8s-helm-temp-chart.yaml new file mode 100644 index 0000000..3611257 --- /dev/null +++ b/build/make/k8s-helm-temp-chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: replaceme +version: 0.0.0 \ No newline at end of file diff --git a/build/make/k8s.mk b/build/make/k8s.mk index c569fa3..6000f80 100644 --- a/build/make/k8s.mk +++ b/build/make/k8s.mk @@ -8,6 +8,11 @@ endif BINARY_YQ = $(UTILITY_BIN_PATH)/yq BINARY_HELM = $(UTILITY_BIN_PATH)/helm +BINARY_HELM_VERSION?=v3.12.0-dev.1.0.20230817154107-a749b663101d +BINARY_HELM_ADDITIONAL_PUSH_ARGS?=--plain-http +BINARY_HELM_ADDITIONAL_PACK_ARGS?= +BINARY_HELM_ADDITIONAL_UNINST_ARGS?= +BINARY_HELM_ADDITIONAL_UPGR_ARGS?= # The productive tag of the image IMAGE ?= @@ -22,6 +27,8 @@ K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR)/make/k8s K8S_RESOURCE_TEMP_YAML ?= $(K8S_RESOURCE_TEMP_FOLDER)/$(ARTIFACT_ID)_$(VERSION).yaml K8S_HELM_TARGET ?= $(K8S_RESOURCE_TEMP_FOLDER)/helm K8S_HELM_RESSOURCES ?= k8s/helm +K8S_HELM_RELEASE_TGZ=${K8S_HELM_TARGET}/${ARTIFACT_ID}-${VERSION}.tgz +K8S_HELM_TARGET_DEP_DIR=charts ##@ K8s - Variables @@ -79,9 +86,9 @@ k8s-apply: k8s-generate $(K8S_POST_GENERATE_TARGETS) ## Applies all generated K8 @kubectl apply -f $(K8S_RESOURCE_TEMP_YAML) --namespace=${NAMESPACE} ##@ K8s - Helm general - -${K8S_HELM_RESSOURCES}/Chart.yaml: ${BINARY_HELM} ## Creates the Chart.yaml-template if missing - @echo "Create Chart.yaml..." +.PHONY: k8s-helm-init-chart +k8s-helm-init-chart: ${BINARY_HELM} ## Creates a Chart.yaml-template with zero values + @echo "Initialize ${K8S_HELM_RESSOURCES}/Chart.yaml..." @mkdir -p ${K8S_HELM_RESSOURCES}/tmp/ @${BINARY_HELM} create ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID} @cp ${K8S_HELM_RESSOURCES}/tmp/${ARTIFACT_ID}/Chart.yaml ${K8S_HELM_RESSOURCES}/ @@ -90,17 +97,19 @@ ${K8S_HELM_RESSOURCES}/Chart.yaml: ${BINARY_HELM} ## Creates the Chart.yaml-temp @sed -i 's/version: .*/version: 0.0.0-replaceme/' ${K8S_HELM_RESSOURCES}/Chart.yaml .PHONY: k8s-helm-delete -k8s-helm-delete: ${BINARY_HELM} ## Uninstalls the current helm chart. +k8s-helm-delete: ${BINARY_HELM} check-k8s-namespace-env-var ## Uninstalls the current helm chart. @echo "Uninstall helm chart" - @${BINARY_HELM} uninstall ${ARTIFACT_ID} + @${BINARY_HELM} uninstall ${ARTIFACT_ID} --namespace=${NAMESPACE} ${BINARY_HELM_ADDITIONAL_UNINST_ARGS} || true .PHONY: k8s-helm-generate-chart -k8s-helm-generate-chart: ${K8S_HELM_RESSOURCES}/Chart.yaml $(K8S_RESOURCE_TEMP_FOLDER) ## Generates the final helm chart. +k8s-helm-generate-chart: ${K8S_HELM_TARGET}/Chart.yaml ## Generates the final helm chart. + +${K8S_HELM_TARGET}/Chart.yaml: $(K8S_RESOURCE_TEMP_FOLDER) @echo "Generate helm chart..." - @rm -drf ${K8S_HELM_TARGET} # delete folder, so Chart.yaml is newly created from template + @rm -drf ${K8S_HELM_TARGET} # delete folder, so the chart is newly created. @mkdir -p ${K8S_HELM_TARGET}/templates @cp $(K8S_RESOURCE_TEMP_YAML) ${K8S_HELM_TARGET}/templates - @cp ${K8S_HELM_RESSOURCES}/Chart.yaml ${K8S_HELM_TARGET} + @cp -r ${K8S_HELM_RESSOURCES}/** ${K8S_HELM_TARGET} @sed -i 's/appVersion: "0.0.0-replaceme"/appVersion: "${VERSION}"/' ${K8S_HELM_TARGET}/Chart.yaml @sed -i 's/version: 0.0.0-replaceme/version: ${VERSION}/' ${K8S_HELM_TARGET}/Chart.yaml @@ -110,9 +119,9 @@ k8s-helm-generate-chart: ${K8S_HELM_RESSOURCES}/Chart.yaml $(K8S_RESOURCE_TEMP_F k8s-helm-generate: k8s-generate k8s-helm-generate-chart ## Generates the final helm chart with dev-urls. .PHONY: k8s-helm-apply -k8s-helm-apply: ${BINARY_HELM} image-import k8s-helm-generate $(K8S_POST_GENERATE_TARGETS) ## Generates and installs the helm chart. +k8s-helm-apply: ${BINARY_HELM} check-k8s-namespace-env-var image-import k8s-helm-generate $(K8S_POST_GENERATE_TARGETS) ## Generates and installs the helm chart. @echo "Apply generated helm chart" - @${BINARY_HELM} upgrade -i ${ARTIFACT_ID} ${K8S_HELM_TARGET} + @${BINARY_HELM} upgrade -i ${ARTIFACT_ID} ${K8S_HELM_TARGET} ${BINARY_HELM_ADDITIONAL_UPGR_ARGS} --namespace ${NAMESPACE} .PHONY: k8s-helm-reinstall k8s-helm-reinstall: k8s-helm-delete k8s-helm-apply ## Uninstalls the current helm chart and reinstalls it. @@ -120,13 +129,55 @@ k8s-helm-reinstall: k8s-helm-delete k8s-helm-apply ## Uninstalls the current hel ##@ K8s - Helm release targets .PHONY: k8s-helm-generate-release -k8s-helm-generate-release: $(K8S_PRE_GENERATE_TARGETS) k8s-helm-generate-chart ## Generates the final helm chart with release urls. +k8s-helm-generate-release: ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml ## Generates the final helm chart with release urls. + +${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml: $(K8S_PRE_GENERATE_TARGETS) ${K8S_HELM_TARGET}/Chart.yaml @sed -i "s/'{{ .Namespace }}'/'{{ .Release.Namespace }}'/" ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml .PHONY: k8s-helm-package-release -k8s-helm-package-release: ${BINARY_HELM} k8s-helm-generate-release $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. +k8s-helm-package-release: ${BINARY_HELM} k8s-helm-delete-existing-tgz ${K8S_HELM_RELEASE_TGZ} k8s-helm-delete-temp-dependencies k8s-helm-remove-dependency-charts ## Generates and packages the helm chart with release urls. + +.PHONY: k8s-helm-delete-existing-tgz +k8s-helm-delete-existing-tgz: ## Remove an existing Helm package. +# remove + @rm -f ${K8S_HELM_RELEASE_TGZ}* + +${K8S_HELM_RELEASE_TGZ}: ${BINARY_HELM} ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml k8s-helm-create-temp-dependencies $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. @echo "Package generated helm chart" - @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} + @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} ${BINARY_HELM_ADDITIONAL_PACK_ARGS} + +.PHONY: k8s-helm-create-temp-dependencies +k8s-helm-create-temp-dependencies: k8s-helm-generate-chart +# we use helm dependencies internally but never use them as "official" dependency because the namespace may differ +# instead we create empty dependencies to satisfy the helm package call and delete the whole directory from the chart.tgz later-on. + @echo "Create helm temp dependencies (if they exist)" + @for dep in `yq -e '.dependencies[].name // ""' ${K8S_HELM_TARGET}/Chart.yaml`; do \ + mkdir -p ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR}/$${dep} ; \ + sed "s|replaceme|$${dep}|g" $(BUILD_DIR)/make/k8s-helm-temp-chart.yaml > ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR}/$${dep}/Chart.yaml ; \ + done + +.PHONY: k8s-helm-delete-temp-dependencies +k8s-helm-delete-temp-dependencies: + @echo "Delete helm temp dependencies (if they exist)" + @rm -rf ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR} + +.PHONY: k8s-helm-remove-dependency-charts +k8s-helm-remove-dependency-charts: ${K8S_HELM_RELEASE_TGZ} +# deleting dirs from a .tgz is hard so un-tar,remove dir,re-tar is a good alternative +# but only if any dependency directory actually exists + @if tar -tf ${K8S_HELM_RELEASE_TGZ} ${ARTIFACT_ID}/${K8S_HELM_TARGET_DEP_DIR} > /dev/null 2>&1; then \ + echo "Remove dependency files from ${K8S_HELM_RELEASE_TGZ}" ; \ + gzip --to-stdout --decompress ${K8S_HELM_RELEASE_TGZ} | \ + tar --to-stdout --delete "${ARTIFACT_ID}/${K8S_HELM_TARGET_DEP_DIR}" -f - | \ + gzip > ${K8S_HELM_RELEASE_TGZ}.temp ; \ + rm ${K8S_HELM_RELEASE_TGZ} && mv ${K8S_HELM_RELEASE_TGZ}.temp ${K8S_HELM_RELEASE_TGZ} ; \ + fi + +.PHONY: chart-import +chart-import: check-all-vars check-k8s-artifact-id k8s-helm-generate-chart k8s-helm-package-release image-import ## Imports the currently available image into the cluster-local registry. + @echo "Import ${K8S_HELM_RELEASE_TGZ} into K8s cluster ${K3CES_REGISTRY_URL_PREFIX}..." + @${BINARY_HELM} push ${K8S_HELM_RELEASE_TGZ} oci://${K3CES_REGISTRY_URL_PREFIX}/k8s ${BINARY_HELM_ADDITIONAL_PUSH_ARGS} + @echo "Done." ##@ K8s - Docker @@ -172,4 +223,4 @@ ${BINARY_YQ}: $(UTILITY_BIN_PATH) ## Download yq locally if necessary. $(call go-get-tool,$(BINARY_YQ),github.com/mikefarah/yq/v4@v4.25.1) ${BINARY_HELM}: $(UTILITY_BIN_PATH) ## Download helm locally if necessary. - $(call go-get-tool,$(BINARY_HELM),helm.sh/helm/v3/cmd/helm@latest) + $(call go-get-tool,$(BINARY_HELM),helm.sh/helm/v3/cmd/helm@${BINARY_HELM_VERSION}) From 22a8f64e2fd1e85ce574b79c2fbabab80b79562e Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 10:18:53 +0200 Subject: [PATCH 04/37] #1 Init chart template --- k8s/helm/Chart.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 k8s/helm/Chart.yaml diff --git a/k8s/helm/Chart.yaml b/k8s/helm/Chart.yaml new file mode 100644 index 0000000..e7044f4 --- /dev/null +++ b/k8s/helm/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: k8s-backup-operator +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.0.0-replaceme + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.0.0-replaceme" From 52d94567d7a38bce2c2a3424325a34f9927dafd6 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 11:51:22 +0200 Subject: [PATCH 05/37] #1 Fix integration test --- go.mod | 8 +- go.sum | 46 ++++++ pkg/config/config.go | 4 +- pkg/controllers/mock_eventRecorder_test.go | 167 +++++++++++++++++++++ pkg/controllers/suite_int_test.go | 111 +++++++++++--- 5 files changed, 313 insertions(+), 23 deletions(-) create mode 100644 pkg/controllers/mock_eventRecorder_test.go diff --git a/go.mod b/go.mod index acc2634..3bbbb99 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,9 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.27.10 + github.com/stretchr/testify v1.8.4 k8s.io/apimachinery v0.28.1 k8s.io/client-go v0.28.1 sigs.k8s.io/controller-runtime v0.16.0 @@ -36,13 +39,15 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.4 // indirect + github.com/stretchr/objx v0.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect @@ -56,6 +61,7 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.28.1 // indirect diff --git a/go.sum b/go.sum index b797d7b..2b79677 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -48,6 +50,7 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -56,6 +59,12 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -63,6 +72,9 @@ github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -78,6 +90,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -108,8 +121,17 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -135,8 +157,10 @@ github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ai github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -193,17 +217,20 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -211,10 +238,16 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -234,6 +267,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= @@ -254,6 +288,12 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= @@ -262,11 +302,17 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/config/config.go b/pkg/config/config.go index 0908eec..7ae54e3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,7 +11,7 @@ import ( const ( StageDevelopment = "development" StageProduction = "production" - stageEnvVar = "STAGE" + StageEnvVar = "STAGE" namespaceEnvVar = "NAMESPACE" ) @@ -55,7 +55,7 @@ func NewOperatorConfig(version string) (*OperatorConfig, error) { func configureStage() { var err error - Stage, err = getEnvVar(stageEnvVar) + Stage, err = getEnvVar(StageEnvVar) if err != nil { log.Error(err, "Error reading stage environment variable. Use stage production") } diff --git a/pkg/controllers/mock_eventRecorder_test.go b/pkg/controllers/mock_eventRecorder_test.go new file mode 100644 index 0000000..1b13d68 --- /dev/null +++ b/pkg/controllers/mock_eventRecorder_test.go @@ -0,0 +1,167 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package controller + +import ( + mock "github.com/stretchr/testify/mock" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// mockEventRecorder is an autogenerated mock type for the eventRecorder type +type mockEventRecorder struct { + mock.Mock +} + +type mockEventRecorder_Expecter struct { + mock *mock.Mock +} + +func (_m *mockEventRecorder) EXPECT() *mockEventRecorder_Expecter { + return &mockEventRecorder_Expecter{mock: &_m.Mock} +} + +// AnnotatedEventf provides a mock function with given fields: object, annotations, eventtype, reason, messageFmt, args +func (_m *mockEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, annotations, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// mockEventRecorder_AnnotatedEventf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnnotatedEventf' +type mockEventRecorder_AnnotatedEventf_Call struct { + *mock.Call +} + +// AnnotatedEventf is a helper method to define mock.On call +// - object runtime.Object +// - annotations map[string]string +// - eventtype string +// - reason string +// - messageFmt string +// - args ...interface{} +func (_e *mockEventRecorder_Expecter) AnnotatedEventf(object interface{}, annotations interface{}, eventtype interface{}, reason interface{}, messageFmt interface{}, args ...interface{}) *mockEventRecorder_AnnotatedEventf_Call { + return &mockEventRecorder_AnnotatedEventf_Call{Call: _e.mock.On("AnnotatedEventf", + append([]interface{}{object, annotations, eventtype, reason, messageFmt}, args...)...)} +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) Run(run func(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{})) *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-5) + for i, a := range args[5:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(runtime.Object), args[1].(map[string]string), args[2].(string), args[3].(string), args[4].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) Return() *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) RunAndReturn(run func(runtime.Object, map[string]string, string, string, string, ...interface{})) *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Return(run) + return _c +} + +// Event provides a mock function with given fields: object, eventtype, reason, message +func (_m *mockEventRecorder) Event(object runtime.Object, eventtype string, reason string, message string) { + _m.Called(object, eventtype, reason, message) +} + +// mockEventRecorder_Event_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Event' +type mockEventRecorder_Event_Call struct { + *mock.Call +} + +// Event is a helper method to define mock.On call +// - object runtime.Object +// - eventtype string +// - reason string +// - message string +func (_e *mockEventRecorder_Expecter) Event(object interface{}, eventtype interface{}, reason interface{}, message interface{}) *mockEventRecorder_Event_Call { + return &mockEventRecorder_Event_Call{Call: _e.mock.On("Event", object, eventtype, reason, message)} +} + +func (_c *mockEventRecorder_Event_Call) Run(run func(object runtime.Object, eventtype string, reason string, message string)) *mockEventRecorder_Event_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(runtime.Object), args[1].(string), args[2].(string), args[3].(string)) + }) + return _c +} + +func (_c *mockEventRecorder_Event_Call) Return() *mockEventRecorder_Event_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_Event_Call) RunAndReturn(run func(runtime.Object, string, string, string)) *mockEventRecorder_Event_Call { + _c.Call.Return(run) + return _c +} + +// Eventf provides a mock function with given fields: object, eventtype, reason, messageFmt, args +func (_m *mockEventRecorder) Eventf(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// mockEventRecorder_Eventf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Eventf' +type mockEventRecorder_Eventf_Call struct { + *mock.Call +} + +// Eventf is a helper method to define mock.On call +// - object runtime.Object +// - eventtype string +// - reason string +// - messageFmt string +// - args ...interface{} +func (_e *mockEventRecorder_Expecter) Eventf(object interface{}, eventtype interface{}, reason interface{}, messageFmt interface{}, args ...interface{}) *mockEventRecorder_Eventf_Call { + return &mockEventRecorder_Eventf_Call{Call: _e.mock.On("Eventf", + append([]interface{}{object, eventtype, reason, messageFmt}, args...)...)} +} + +func (_c *mockEventRecorder_Eventf_Call) Run(run func(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{})) *mockEventRecorder_Eventf_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-4) + for i, a := range args[4:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(runtime.Object), args[1].(string), args[2].(string), args[3].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockEventRecorder_Eventf_Call) Return() *mockEventRecorder_Eventf_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_Eventf_Call) RunAndReturn(run func(runtime.Object, string, string, string, ...interface{})) *mockEventRecorder_Eventf_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockEventRecorder interface { + mock.TestingT + Cleanup(func()) +} + +// newMockEventRecorder creates a new instance of mockEventRecorder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockEventRecorder(t mockConstructorTestingTnewMockEventRecorder) *mockEventRecorder { + mock := &mockEventRecorder{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/controllers/suite_int_test.go b/pkg/controllers/suite_int_test.go index a07d79e..c9fc7c6 100644 --- a/pkg/controllers/suite_int_test.go +++ b/pkg/controllers/suite_int_test.go @@ -4,61 +4,132 @@ package controller import ( + "context" + "os" "path/filepath" "testing" + "time" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "github.com/onsi/ginkgo" + "github.com/onsi/gomega" + + "github.com/cloudogu/k8s-backup-operator/pkg/api/ecosystem" k8sv1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + "github.com/cloudogu/k8s-backup-operator/pkg/config" //+kubebuilder:scaffold:imports ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -var cfg *rest.Config -var k8sClient client.Client var testEnv *envtest.Environment +var cfg *rest.Config +var cancel context.CancelFunc + +// Used in other integration tests +var ( + ecosystemClientSet ecosystem.Interface + recorderMock *mockEventRecorder + namespace = "default" +) + +const TimeoutInterval = time.Second * 10 +const PollingInterval = time.Second * 1 + +var oldGetConfig func() (*rest.Config, error) +var oldGetConfigOrDie func() *rest.Config func TestControllers(t *testing.T) { - RegisterFailHandler(Fail) + gomega.RegisterFailHandler(ginkgo.Fail) - RunSpecs(t, "Controller Suite") + ginkgo.RunSpecs(t, "Controller Suite") } -var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) +var _ = ginkgo.BeforeSuite(func() { + // We need to ensure that the development stage flag is not passed by our makefiles to prevent the component operator + // from running in the developing mode. The developing mode changes some operator behaviour. Our integration test + // aim to test the production functionality of the operator. + err := os.Unsetenv(config.StageEnvVar) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + err = os.Setenv(config.StageEnvVar, config.StageProduction) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + config.Stage = config.StageProduction + + logf.SetLogger(zap.New(zap.WriteTo(ginkgo.GinkgoWriter), zap.UseDevMode(true))) - By("bootstrapping test environment") + var ctx context.Context + ctx, cancel = context.WithCancel(context.TODO()) + + ginkgo.By("bootstrapping test environment") testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } - var err error // cfg is defined in this file globally. cfg, err = testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + gomega.Expect(cfg).NotTo(gomega.BeNil()) + + oldGetConfig = ctrl.GetConfig + ctrl.GetConfig = func() (*rest.Config, error) { + return cfg, nil + } + + oldGetConfigOrDie = ctrl.GetConfigOrDie + ctrl.GetConfigOrDie = func() *rest.Config { + return cfg + } err = k8sv1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) //+kubebuilder:scaffold:scheme + k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme.Scheme, + }) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + gomega.Expect(k8sManager).NotTo(gomega.BeNil()) + t := &testing.T{} + recorderMock = newMockEventRecorder(t) - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) + clientSet, err := kubernetes.NewForConfig(cfg) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) -}) + ecosystemClientSet, err = ecosystem.NewClientSet(k8sManager.GetConfig(), clientSet) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + backupReconciler := NewBackupReconciler(ecosystemClientSet, recorderMock, namespace) + gomega.Expect(backupReconciler).NotTo(gomega.BeNil()) -var _ = AfterSuite(func() { - By("tearing down the test environment") + err = backupReconciler.SetupWithManager(k8sManager) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + restoreReconciler := NewRestoreReconciler(ecosystemClientSet, recorderMock, namespace) + gomega.Expect(restoreReconciler).NotTo(gomega.BeNil()) + + err = restoreReconciler.SetupWithManager(k8sManager) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + go func() { + err = k8sManager.Start(ctx) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + }() +}, 60) + +var _ = ginkgo.AfterSuite(func() { + cancel() + ginkgo.By("tearing down the test environment") err := testEnv.Stop() - Expect(err).NotTo(HaveOccurred()) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ctrl.GetConfig = oldGetConfig + ctrl.GetConfigOrDie = oldGetConfigOrDie }) From 1a5017586e8d9706c12e94252e7f578eb7e375b6 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 14:21:35 +0200 Subject: [PATCH 06/37] #1 Fix incorrect path in makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fcf1998..fb112a4 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust @echo "Generate manifests..." @$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases @make template-crd-labels - @cp config/crd/bases/k8s.cloudogu.com_dogus.yaml api/v1/ + @cp config/crd/bases/k8s.cloudogu.com_dogus.yaml pkg/api/v1/ .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. From a146c58f4b64a0fb40f2aab45140ebfcbdc5be31 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 14:47:52 +0200 Subject: [PATCH 07/37] #1 Fix artifact archiving in Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index f3a0aa5..a9a695b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -60,7 +60,7 @@ node('docker') { stage('Generate k8s Resources') { make 'k8s-create-temporary-resource' - archiveArtifacts 'target/*.yaml' + archiveArtifacts 'target/make/k8s/*.yaml' } } From 2a344b9642eefee6c6d9480d654dbcaef39daf8a Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 15:06:16 +0200 Subject: [PATCH 08/37] #1 Update makefiles and regenerate resources --- Makefile | 2 +- build/make/k8s-controller.mk | 2 +- build/make/k8s.mk | 25 +--- .../crd/bases/k8s.cloudogu.com_backups.yaml | 5 +- config/crd/bases/k8s.cloudogu.com_dogus.yaml | 109 ++++++++++++++++++ .../crd/bases/k8s.cloudogu.com_restores.yaml | 5 +- config/manager/kustomization.yaml | 6 + pkg/api/v1/k8s.cloudogu.com_dogus.yaml | 109 ++++++++++++++++++ pkg/api/v1/zz_generated.deepcopy.go | 1 - 9 files changed, 238 insertions(+), 26 deletions(-) create mode 100644 config/crd/bases/k8s.cloudogu.com_dogus.yaml create mode 100644 pkg/api/v1/k8s.cloudogu.com_dogus.yaml diff --git a/Makefile b/Makefile index fb112a4..2044dfd 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ VERSION=0.1.0 IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} GOTAG?=1.21 -MAKEFILES_VERSION=7.12.1 +MAKEFILES_VERSION=7.13.0 LINT_VERSION=v1.52.1 STAGE?=production diff --git a/build/make/k8s-controller.mk b/build/make/k8s-controller.mk index d7129ad..5bdd885 100644 --- a/build/make/k8s-controller.mk +++ b/build/make/k8s-controller.mk @@ -83,7 +83,7 @@ k8s-integration-test: $(K8S_INTEGRATION_TEST_DIR) manifests generate envtest ## CONTROLLER_GEN = $(UTILITY_BIN_PATH)/controller-gen .PHONY: controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.11.3) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0) KUSTOMIZE = $(UTILITY_BIN_PATH)/kustomize .PHONY: kustomize diff --git a/build/make/k8s.mk b/build/make/k8s.mk index 6000f80..9766b26 100644 --- a/build/make/k8s.mk +++ b/build/make/k8s.mk @@ -102,7 +102,7 @@ k8s-helm-delete: ${BINARY_HELM} check-k8s-namespace-env-var ## Uninstalls the cu @${BINARY_HELM} uninstall ${ARTIFACT_ID} --namespace=${NAMESPACE} ${BINARY_HELM_ADDITIONAL_UNINST_ARGS} || true .PHONY: k8s-helm-generate-chart -k8s-helm-generate-chart: ${K8S_HELM_TARGET}/Chart.yaml ## Generates the final helm chart. +k8s-helm-generate-chart: ${K8S_HELM_TARGET}/Chart.yaml k8s-helm-create-temp-dependencies ## Generates the final helm chart. ${K8S_HELM_TARGET}/Chart.yaml: $(K8S_RESOURCE_TEMP_FOLDER) @echo "Generate helm chart..." @@ -135,19 +135,19 @@ ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml: $(K8S_PRE_GENERATE_ @sed -i "s/'{{ .Namespace }}'/'{{ .Release.Namespace }}'/" ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml .PHONY: k8s-helm-package-release -k8s-helm-package-release: ${BINARY_HELM} k8s-helm-delete-existing-tgz ${K8S_HELM_RELEASE_TGZ} k8s-helm-delete-temp-dependencies k8s-helm-remove-dependency-charts ## Generates and packages the helm chart with release urls. +k8s-helm-package-release: ${BINARY_HELM} k8s-helm-delete-existing-tgz ${K8S_HELM_RELEASE_TGZ} ## Generates and packages the helm chart with release urls. .PHONY: k8s-helm-delete-existing-tgz k8s-helm-delete-existing-tgz: ## Remove an existing Helm package. # remove @rm -f ${K8S_HELM_RELEASE_TGZ}* -${K8S_HELM_RELEASE_TGZ}: ${BINARY_HELM} ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml k8s-helm-create-temp-dependencies $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. +${K8S_HELM_RELEASE_TGZ}: ${BINARY_HELM} ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ID)_$(VERSION).yaml k8s-helm-generate-chart $(K8S_POST_GENERATE_TARGETS) ## Generates and packages the helm chart with release urls. @echo "Package generated helm chart" @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} ${BINARY_HELM_ADDITIONAL_PACK_ARGS} .PHONY: k8s-helm-create-temp-dependencies -k8s-helm-create-temp-dependencies: k8s-helm-generate-chart +k8s-helm-create-temp-dependencies: ${K8S_HELM_TARGET}/Chart.yaml # we use helm dependencies internally but never use them as "official" dependency because the namespace may differ # instead we create empty dependencies to satisfy the helm package call and delete the whole directory from the chart.tgz later-on. @echo "Create helm temp dependencies (if they exist)" @@ -156,23 +156,6 @@ k8s-helm-create-temp-dependencies: k8s-helm-generate-chart sed "s|replaceme|$${dep}|g" $(BUILD_DIR)/make/k8s-helm-temp-chart.yaml > ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR}/$${dep}/Chart.yaml ; \ done -.PHONY: k8s-helm-delete-temp-dependencies -k8s-helm-delete-temp-dependencies: - @echo "Delete helm temp dependencies (if they exist)" - @rm -rf ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR} - -.PHONY: k8s-helm-remove-dependency-charts -k8s-helm-remove-dependency-charts: ${K8S_HELM_RELEASE_TGZ} -# deleting dirs from a .tgz is hard so un-tar,remove dir,re-tar is a good alternative -# but only if any dependency directory actually exists - @if tar -tf ${K8S_HELM_RELEASE_TGZ} ${ARTIFACT_ID}/${K8S_HELM_TARGET_DEP_DIR} > /dev/null 2>&1; then \ - echo "Remove dependency files from ${K8S_HELM_RELEASE_TGZ}" ; \ - gzip --to-stdout --decompress ${K8S_HELM_RELEASE_TGZ} | \ - tar --to-stdout --delete "${ARTIFACT_ID}/${K8S_HELM_TARGET_DEP_DIR}" -f - | \ - gzip > ${K8S_HELM_RELEASE_TGZ}.temp ; \ - rm ${K8S_HELM_RELEASE_TGZ} && mv ${K8S_HELM_RELEASE_TGZ}.temp ${K8S_HELM_RELEASE_TGZ} ; \ - fi - .PHONY: chart-import chart-import: check-all-vars check-k8s-artifact-id k8s-helm-generate-chart k8s-helm-package-release image-import ## Imports the currently available image into the cluster-local registry. @echo "Import ${K8S_HELM_RELEASE_TGZ} into K8s cluster ${K3CES_REGISTRY_URL_PREFIX}..." diff --git a/config/crd/bases/k8s.cloudogu.com_backups.yaml b/config/crd/bases/k8s.cloudogu.com_backups.yaml index 334bccd..8925efd 100644 --- a/config/crd/bases/k8s.cloudogu.com_backups.yaml +++ b/config/crd/bases/k8s.cloudogu.com_backups.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.12.0 + controller-gen.kubebuilder.io/version: v0.13.0 name: backups.k8s.cloudogu.com spec: group: k8s.cloudogu.com @@ -41,6 +41,9 @@ spec: type: object status: description: BackupStatus defines the observed state of Backup + properties: + status: + type: string type: object type: object served: true diff --git a/config/crd/bases/k8s.cloudogu.com_dogus.yaml b/config/crd/bases/k8s.cloudogu.com_dogus.yaml new file mode 100644 index 0000000..1d44eab --- /dev/null +++ b/config/crd/bases/k8s.cloudogu.com_dogus.yaml @@ -0,0 +1,109 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: backups.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Backup + listKind: BackupList + plural: backups + singular: backup + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Backup is the Schema for the backups API + 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: BackupSpec defines the desired state of Backup + properties: + foo: + description: Foo is an example field of Backup. Edit backup_types.go + to remove/update + type: string + type: object + status: + description: BackupStatus defines the observed state of Backup + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: restores.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Restore + listKind: RestoreList + plural: restores + singular: restore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Restore is the Schema for the restores API + 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: RestoreSpec defines the desired state of Restore + properties: + foo: + description: Foo is an example field of Restore. Edit restore_types.go + to remove/update + type: string + type: object + status: + description: RestoreStatus defines the observed state of Restore + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/k8s.cloudogu.com_restores.yaml b/config/crd/bases/k8s.cloudogu.com_restores.yaml index d314e7d..58ecbca 100644 --- a/config/crd/bases/k8s.cloudogu.com_restores.yaml +++ b/config/crd/bases/k8s.cloudogu.com_restores.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.12.0 + controller-gen.kubebuilder.io/version: v0.13.0 name: restores.k8s.cloudogu.com spec: group: k8s.cloudogu.com @@ -41,6 +41,9 @@ spec: type: object status: description: RestoreStatus defines the observed state of Restore + properties: + status: + type: string type: object type: object served: true diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5c5f0b8..e0b8d8b 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,2 +1,8 @@ resources: - manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: cloudogu/k8s-backup-operator + newTag: 0.1.0 diff --git a/pkg/api/v1/k8s.cloudogu.com_dogus.yaml b/pkg/api/v1/k8s.cloudogu.com_dogus.yaml new file mode 100644 index 0000000..1d44eab --- /dev/null +++ b/pkg/api/v1/k8s.cloudogu.com_dogus.yaml @@ -0,0 +1,109 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: backups.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Backup + listKind: BackupList + plural: backups + singular: backup + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Backup is the Schema for the backups API + 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: BackupSpec defines the desired state of Backup + properties: + foo: + description: Foo is an example field of Backup. Edit backup_types.go + to remove/update + type: string + type: object + status: + description: BackupStatus defines the observed state of Backup + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: restores.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Restore + listKind: RestoreList + plural: restores + singular: restore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Restore is the Schema for the restores API + 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: RestoreSpec defines the desired state of Restore + properties: + foo: + description: Foo is an example field of Restore. Edit restore_types.go + to remove/update + type: string + type: object + status: + description: RestoreStatus defines the observed state of Restore + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/api/v1/zz_generated.deepcopy.go b/pkg/api/v1/zz_generated.deepcopy.go index f9afe9b..59ee948 100644 --- a/pkg/api/v1/zz_generated.deepcopy.go +++ b/pkg/api/v1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* This file was generated with "make generate". From 45106ca7bb34f25319b7c81b594256702317ac98 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 15:07:46 +0200 Subject: [PATCH 09/37] #1 Fix k8s resource lint in Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index a9a695b..1369b38 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -140,7 +140,7 @@ void stageLintK8SResources() { .image(kubevalImage) .inside("-v ${WORKSPACE}/target:/data -t --entrypoint=") { - sh "kubeval /data/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" + sh "kubeval /data/make/k8s/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" } } From 94dd03d1b5f38c46cda8c6219ea488f1ff5d17f5 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 15:11:09 +0200 Subject: [PATCH 10/37] #1 Use target dir for storing k8s resources instead of changing all the references --- Jenkinsfile | 4 ++-- Makefile | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1369b38..f3a0aa5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -60,7 +60,7 @@ node('docker') { stage('Generate k8s Resources') { make 'k8s-create-temporary-resource' - archiveArtifacts 'target/make/k8s/*.yaml' + archiveArtifacts 'target/*.yaml' } } @@ -140,7 +140,7 @@ void stageLintK8SResources() { .image(kubevalImage) .inside("-v ${WORKSPACE}/target:/data -t --entrypoint=") { - sh "kubeval /data/make/k8s/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" + sh "kubeval /data/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas" } } diff --git a/Makefile b/Makefile index 2044dfd..93180d2 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ include build/make/digital-signature.mk include build/make/mocks.mk PRE_COMPILE=generate +K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR) K8S_PRE_GENERATE_TARGETS=k8s-create-temporary-resource template-dev-only-image-pull-policy include build/make/k8s-controller.mk From 353600c3fa508bc885d59185d2575f5b05ff63ba Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 15:59:36 +0200 Subject: [PATCH 11/37] #1 Replace old name --- config/default/kustomization.yaml | 2 +- config/manager/manager.yaml | 8 ++++---- config/prometheus/monitor.yaml | 4 ++-- config/rbac/auth_proxy_client_clusterrole.yaml | 4 ++-- config/rbac/auth_proxy_role.yaml | 4 ++-- config/rbac/auth_proxy_role_binding.yaml | 4 ++-- config/rbac/auth_proxy_service.yaml | 4 ++-- config/rbac/backup_editor_role.yaml | 4 ++-- config/rbac/backup_viewer_role.yaml | 4 ++-- config/rbac/leader_election_role.yaml | 4 ++-- config/rbac/leader_election_role_binding.yaml | 4 ++-- config/rbac/restore_editor_role.yaml | 4 ++-- config/rbac/restore_viewer_role.yaml | 4 ++-- config/rbac/role_binding.yaml | 4 ++-- config/rbac/service_account.yaml | 4 ++-- config/samples/k8s_v1_backup.yaml | 4 ++-- config/samples/k8s_v1_restore.yaml | 4 ++-- 17 files changed, 35 insertions(+), 35 deletions(-) diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index e188eef..1080419 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -7,7 +7,7 @@ # "wordpress" becomes "alices-wordpress". # Note that it should also match with the prefix (text before '-') of the namespace # field above. -namePrefix: kubebuilder-backup-operator- +namePrefix: k8s-backup-operator- # Labels to add to all resources and selectors. #labels: diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 6508554..27229b9 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: namespace app.kubernetes.io/instance: system app.kubernetes.io/component: manager - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: system --- @@ -21,8 +21,8 @@ metadata: app.kubernetes.io/name: deployment app.kubernetes.io/instance: controller-manager app.kubernetes.io/component: manager - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize spec: selector: diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index 0ade53b..2fdf94d 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -8,8 +8,8 @@ metadata: app.kubernetes.io/name: servicemonitor app.kubernetes.io/instance: controller-manager-metrics-monitor app.kubernetes.io/component: metrics - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-monitor namespace: system diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml index 3d67e80..184cd07 100644 --- a/config/rbac/auth_proxy_client_clusterrole.yaml +++ b/config/rbac/auth_proxy_client_clusterrole.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: metrics-reader app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: metrics-reader rules: diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml index fbe062b..fe94a2b 100644 --- a/config/rbac/auth_proxy_role.yaml +++ b/config/rbac/auth_proxy_role.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: proxy-role app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: proxy-role rules: diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index ebf905f..695b31d 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: clusterrolebinding app.kubernetes.io/instance: proxy-rolebinding app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: proxy-rolebinding roleRef: diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml index 8f332a7..e7d2ef3 100644 --- a/config/rbac/auth_proxy_service.yaml +++ b/config/rbac/auth_proxy_service.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: service app.kubernetes.io/instance: controller-manager-metrics-service app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-service namespace: system diff --git a/config/rbac/backup_editor_role.yaml b/config/rbac/backup_editor_role.yaml index 699ecfa..eb28196 100644 --- a/config/rbac/backup_editor_role.yaml +++ b/config/rbac/backup_editor_role.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: backup-editor-role app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: backup-editor-role rules: diff --git a/config/rbac/backup_viewer_role.yaml b/config/rbac/backup_viewer_role.yaml index 2c0a497..1a88d3f 100644 --- a/config/rbac/backup_viewer_role.yaml +++ b/config/rbac/backup_viewer_role.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: backup-viewer-role app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: backup-viewer-role rules: diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml index 592e4a5..d975352 100644 --- a/config/rbac/leader_election_role.yaml +++ b/config/rbac/leader_election_role.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: role app.kubernetes.io/instance: leader-election-role app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: leader-election-role rules: diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml index 3514b04..96ede47 100644 --- a/config/rbac/leader_election_role_binding.yaml +++ b/config/rbac/leader_election_role_binding.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: rolebinding app.kubernetes.io/instance: leader-election-rolebinding app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: leader-election-rolebinding roleRef: diff --git a/config/rbac/restore_editor_role.yaml b/config/rbac/restore_editor_role.yaml index fa1ea21..858bf22 100644 --- a/config/rbac/restore_editor_role.yaml +++ b/config/rbac/restore_editor_role.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: restore-editor-role app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: restore-editor-role rules: diff --git a/config/rbac/restore_viewer_role.yaml b/config/rbac/restore_viewer_role.yaml index 1966ec1..f7630fe 100644 --- a/config/rbac/restore_viewer_role.yaml +++ b/config/rbac/restore_viewer_role.yaml @@ -6,8 +6,8 @@ metadata: app.kubernetes.io/name: clusterrole app.kubernetes.io/instance: restore-viewer-role app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: restore-viewer-role rules: diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index 0f226fb..933bd32 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: clusterrolebinding app.kubernetes.io/instance: manager-rolebinding app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: manager-rolebinding roleRef: diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml index 0433299..87d2519 100644 --- a/config/rbac/service_account.yaml +++ b/config/rbac/service_account.yaml @@ -5,8 +5,8 @@ metadata: app.kubernetes.io/name: serviceaccount app.kubernetes.io/instance: controller-manager-sa app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: kubebuilder-backup-operator - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager namespace: system diff --git a/config/samples/k8s_v1_backup.yaml b/config/samples/k8s_v1_backup.yaml index 3678b90..ecf4324 100644 --- a/config/samples/k8s_v1_backup.yaml +++ b/config/samples/k8s_v1_backup.yaml @@ -4,9 +4,9 @@ metadata: labels: app.kubernetes.io/name: backup app.kubernetes.io/instance: backup-sample - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator name: backup-sample spec: # TODO(user): Add fields here diff --git a/config/samples/k8s_v1_restore.yaml b/config/samples/k8s_v1_restore.yaml index 91be4e0..98e1b8a 100644 --- a/config/samples/k8s_v1_restore.yaml +++ b/config/samples/k8s_v1_restore.yaml @@ -4,9 +4,9 @@ metadata: labels: app.kubernetes.io/name: restore app.kubernetes.io/instance: restore-sample - app.kubernetes.io/part-of: kubebuilder-backup-operator + app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: kubebuilder-backup-operator + app.kubernetes.io/created-by: k8s-backup-operator name: restore-sample spec: # TODO(user): Add fields here From 8c0553395880cfdba939df9c3ad3ab95f6e8f64a Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:01:44 +0200 Subject: [PATCH 12/37] #1 Remove generated system namespace --- config/default/manager_auth_proxy_patch.yaml | 1 - config/manager/manager.yaml | 14 -------------- config/prometheus/monitor.yaml | 1 - config/rbac/auth_proxy_role_binding.yaml | 1 - config/rbac/auth_proxy_service.yaml | 1 - config/rbac/leader_election_role_binding.yaml | 1 - config/rbac/role_binding.yaml | 1 - config/rbac/service_account.yaml | 1 - 8 files changed, 21 deletions(-) diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index 73fad2a..d27bd9e 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -4,7 +4,6 @@ apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager - namespace: system spec: template: spec: diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 27229b9..aa9aea1 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -1,21 +1,7 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: namespace - app.kubernetes.io/instance: system - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: k8s-backup-operator - app.kubernetes.io/part-of: k8s-backup-operator - app.kubernetes.io/managed-by: kustomize - name: system ---- apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager - namespace: system labels: control-plane: controller-manager app.kubernetes.io/name: deployment diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index 2fdf94d..0d2f940 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -12,7 +12,6 @@ metadata: app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-monitor - namespace: system spec: endpoints: - path: /metrics diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index 695b31d..4875898 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -16,4 +16,3 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: system diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml index e7d2ef3..84cde63 100644 --- a/config/rbac/auth_proxy_service.yaml +++ b/config/rbac/auth_proxy_service.yaml @@ -10,7 +10,6 @@ metadata: app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-service - namespace: system spec: ports: - name: https diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml index 96ede47..89d64cb 100644 --- a/config/rbac/leader_election_role_binding.yaml +++ b/config/rbac/leader_election_role_binding.yaml @@ -16,4 +16,3 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: system diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index 933bd32..7f461e8 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -16,4 +16,3 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: system diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml index 87d2519..3fc2732 100644 --- a/config/rbac/service_account.yaml +++ b/config/rbac/service_account.yaml @@ -9,4 +9,3 @@ metadata: app.kubernetes.io/part-of: k8s-backup-operator app.kubernetes.io/managed-by: kustomize name: controller-manager - namespace: system From 8a1affe65759d2f51eba4b237cb02680d689d114 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:12:03 +0200 Subject: [PATCH 13/37] #1 Remove incorrect command from container add env vars to container add imagepullpolicy to container --- config/manager/manager.yaml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index aa9aea1..f3bd60b 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -52,11 +52,19 @@ spec: # seccompProfile: # type: RuntimeDefault containers: - - command: - - /manager - args: + - args: - --leader-elect + env: + - name: STAGE + value: "production" + - name: LOG_LEVEL + value: "debug" + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace image: controller:latest + imagePullPolicy: IfNotPresent name: manager securityContext: allowPrivilegeEscalation: false From f61fb20268129bfe14d879bb8515de3810a504fd Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:18:44 +0200 Subject: [PATCH 14/37] #1 Add namespace to role-bindings --- config/rbac/auth_proxy_role_binding.yaml | 1 + config/rbac/role_binding.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index 4875898..94b047d 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -16,3 +16,4 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager + namespace: '{{ .Namespace }}' diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index 7f461e8..fa8d6f4 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -16,3 +16,4 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager + namespace: '{{ .Namespace }}' From 261c6e37743506a58fd2f8b542cde8b91d4a96a1 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:19:06 +0200 Subject: [PATCH 15/37] #1 Add labels to generated CRDs --- config/crd/bases/k8s.cloudogu.com_backups.yaml | 3 +++ config/crd/bases/k8s.cloudogu.com_restores.yaml | 3 +++ pkg/api/v1/backup_types.go | 1 + pkg/api/v1/restore_types.go | 1 + 4 files changed, 8 insertions(+) diff --git a/config/crd/bases/k8s.cloudogu.com_backups.yaml b/config/crd/bases/k8s.cloudogu.com_backups.yaml index 8925efd..86568e6 100644 --- a/config/crd/bases/k8s.cloudogu.com_backups.yaml +++ b/config/crd/bases/k8s.cloudogu.com_backups.yaml @@ -4,6 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator name: backups.k8s.cloudogu.com spec: group: k8s.cloudogu.com diff --git a/config/crd/bases/k8s.cloudogu.com_restores.yaml b/config/crd/bases/k8s.cloudogu.com_restores.yaml index 58ecbca..8e8f2d1 100644 --- a/config/crd/bases/k8s.cloudogu.com_restores.yaml +++ b/config/crd/bases/k8s.cloudogu.com_restores.yaml @@ -4,6 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator name: restores.k8s.cloudogu.com spec: group: k8s.cloudogu.com diff --git a/pkg/api/v1/backup_types.go b/pkg/api/v1/backup_types.go index 4d57f38..85b55dd 100644 --- a/pkg/api/v1/backup_types.go +++ b/pkg/api/v1/backup_types.go @@ -29,6 +29,7 @@ type BackupStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:metadata:labels=app=ces;app.kubernetes.io/name=k8s-backup-operator // Backup is the Schema for the backups API type Backup struct { diff --git a/pkg/api/v1/restore_types.go b/pkg/api/v1/restore_types.go index 92228bc..c1c2c00 100644 --- a/pkg/api/v1/restore_types.go +++ b/pkg/api/v1/restore_types.go @@ -29,6 +29,7 @@ type RestoreStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:metadata:labels=app=ces;app.kubernetes.io/name=k8s-backup-operator // Restore is the Schema for the restores API type Restore struct { From b242227e12c3df79f0ad9406bbcaa108defb2951 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:33:20 +0200 Subject: [PATCH 16/37] #1 Add labels to generated resources --- config/default/kustomization.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 1080419..c4dfc40 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,6 +1,7 @@ # Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue +commonLabels: + app: ces + app.kubernetes.io/name: k8s-backup-operator # Value of this field is prepended to the # names of all resources, e.g. a deployment named From c0a29dcdca078cf8fa077c2f74c99a1616cf77da Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Thu, 31 Aug 2023 16:39:09 +0200 Subject: [PATCH 17/37] #1 Add helm release creation --- Jenkinsfile | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index f3a0aa5..e02c6b3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,6 +19,8 @@ goVersion = "1.21" repositoryOwner = "cloudogu" repositoryName = "k8s-backup-operator" project = "github.com/${repositoryOwner}/${repositoryName}" +registry = "registry.cloudogu.com" +registry_namespace = "k8s" // Configuration of branches productionReleaseBranch = "main" @@ -189,6 +191,7 @@ void stageAutomaticRelease() { if (gitflow.isReleaseBranch()) { String releaseVersion = git.getSimpleBranchName() String dockerReleaseVersion = releaseVersion.split("v")[1] + String controllerVersion = makefile.getVersion() stage('Build & Push Image') { withCredentials([usernamePassword(credentialsId: 'cesmarvin', @@ -225,14 +228,27 @@ void stageAutomaticRelease() { } stage('Push to Registry') { - Makefile makefile = new Makefile(this) - String controllerVersion = makefile.getVersion() GString targetOperatorResourceYaml = "target/${repositoryName}_${controllerVersion}.yaml" DoguRegistry registry = new DoguRegistry(this) registry.pushK8sYaml(targetOperatorResourceYaml, repositoryName, "k8s", "${controllerVersion}") } + stage('Push Helm chart to Harbor') { + new Docker(this) + .image("golang:${goVersion}") + .mountJenkinsUser() + .inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}") + { + make 'k8s-helm-package-release' + + withCredentials([usernamePassword(credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) { + sh ".bin/helm registry login ${registry} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'" + sh ".bin/helm push target/helm/${repositoryName}-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/" + } + } + } + stage('Add Github-Release') { releaseId = github.createReleaseWithChangelog(releaseVersion, changelog, productionReleaseBranch) } From c5794f291b14b2dd805c66dc5781870242295d2c Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 09:39:21 +0200 Subject: [PATCH 18/37] #1 Use Roles instead of ClusterRoles for RBAC --- config/rbac/auth_proxy_role.yaml | 2 +- config/rbac/auth_proxy_role_binding.yaml | 3 +-- config/rbac/backup_editor_role.yaml | 2 +- config/rbac/backup_viewer_role.yaml | 2 +- config/rbac/restore_editor_role.yaml | 2 +- config/rbac/restore_viewer_role.yaml | 2 +- config/rbac/role_binding.yaml | 3 +-- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml index fe94a2b..465aa94 100644 --- a/config/rbac/auth_proxy_role.yaml +++ b/config/rbac/auth_proxy_role.yaml @@ -1,5 +1,5 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: labels: app.kubernetes.io/name: clusterrole diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index 94b047d..5fc8828 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -1,5 +1,5 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: labels: app.kubernetes.io/name: clusterrolebinding @@ -16,4 +16,3 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: '{{ .Namespace }}' diff --git a/config/rbac/backup_editor_role.yaml b/config/rbac/backup_editor_role.yaml index eb28196..c7feb79 100644 --- a/config/rbac/backup_editor_role.yaml +++ b/config/rbac/backup_editor_role.yaml @@ -1,6 +1,6 @@ # permissions for end users to edit backups. apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: labels: app.kubernetes.io/name: clusterrole diff --git a/config/rbac/backup_viewer_role.yaml b/config/rbac/backup_viewer_role.yaml index 1a88d3f..75f88dc 100644 --- a/config/rbac/backup_viewer_role.yaml +++ b/config/rbac/backup_viewer_role.yaml @@ -1,6 +1,6 @@ # permissions for end users to view backups. apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: labels: app.kubernetes.io/name: clusterrole diff --git a/config/rbac/restore_editor_role.yaml b/config/rbac/restore_editor_role.yaml index 858bf22..e69458f 100644 --- a/config/rbac/restore_editor_role.yaml +++ b/config/rbac/restore_editor_role.yaml @@ -1,6 +1,6 @@ # permissions for end users to edit restores. apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: labels: app.kubernetes.io/name: clusterrole diff --git a/config/rbac/restore_viewer_role.yaml b/config/rbac/restore_viewer_role.yaml index f7630fe..fffec6e 100644 --- a/config/rbac/restore_viewer_role.yaml +++ b/config/rbac/restore_viewer_role.yaml @@ -1,6 +1,6 @@ # permissions for end users to view restores. apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: labels: app.kubernetes.io/name: clusterrole diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index fa8d6f4..7314691 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -1,5 +1,5 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: labels: app.kubernetes.io/name: clusterrolebinding @@ -16,4 +16,3 @@ roleRef: subjects: - kind: ServiceAccount name: controller-manager - namespace: '{{ .Namespace }}' From 22243a53ea7da2a56880c56283e126ee19f3f9b9 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 09:48:46 +0200 Subject: [PATCH 19/37] #1 Remove deprecated logtostderr flag from rbac-proxy --- config/default/manager_auth_proxy_patch.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index d27bd9e..ecb25ef 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -18,7 +18,6 @@ spec: args: - "--secure-listen-address=0.0.0.0:8443" - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - "--v=0" ports: - containerPort: 8443 From 47654268e24aff7f9122ba529fe1c84d7c8d4029 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 09:49:45 +0200 Subject: [PATCH 20/37] #1 Update makefiles to 7.13.1 --- Makefile | 2 +- build/make/k8s.mk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 93180d2..0c1f67c 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ VERSION=0.1.0 IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION} IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION} GOTAG?=1.21 -MAKEFILES_VERSION=7.13.0 +MAKEFILES_VERSION=7.13.1 LINT_VERSION=v1.52.1 STAGE?=production diff --git a/build/make/k8s.mk b/build/make/k8s.mk index 9766b26..8a7af58 100644 --- a/build/make/k8s.mk +++ b/build/make/k8s.mk @@ -147,11 +147,11 @@ ${K8S_HELM_RELEASE_TGZ}: ${BINARY_HELM} ${K8S_HELM_TARGET}/templates/$(ARTIFACT_ @${BINARY_HELM} package ${K8S_HELM_TARGET} -d ${K8S_HELM_TARGET} ${BINARY_HELM_ADDITIONAL_PACK_ARGS} .PHONY: k8s-helm-create-temp-dependencies -k8s-helm-create-temp-dependencies: ${K8S_HELM_TARGET}/Chart.yaml +k8s-helm-create-temp-dependencies: ${BINARY_YQ} ${K8S_HELM_TARGET}/Chart.yaml # we use helm dependencies internally but never use them as "official" dependency because the namespace may differ # instead we create empty dependencies to satisfy the helm package call and delete the whole directory from the chart.tgz later-on. @echo "Create helm temp dependencies (if they exist)" - @for dep in `yq -e '.dependencies[].name // ""' ${K8S_HELM_TARGET}/Chart.yaml`; do \ + @for dep in `${BINARY_YQ} -e '.dependencies[].name // ""' ${K8S_HELM_TARGET}/Chart.yaml`; do \ mkdir -p ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR}/$${dep} ; \ sed "s|replaceme|$${dep}|g" $(BUILD_DIR)/make/k8s-helm-temp-chart.yaml > ${K8S_HELM_TARGET}/${K8S_HELM_TARGET_DEP_DIR}/$${dep}/Chart.yaml ; \ done From 9cf53efb36c834a3e64c4136f3b92ff9fd988bfc Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 09:56:10 +0200 Subject: [PATCH 21/37] #1 Handle unhandled errors --- main.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 1e3e0de..6bbc6f2 100644 --- a/main.go +++ b/main.go @@ -54,6 +54,9 @@ func main() { func startOperator() error { operatorConfig, err := config.NewOperatorConfig(Version) + if err != nil { + return fmt.Errorf("unable to create operator config: %w", err) + } options := getK8sManagerOptions(operatorConfig) k8sManager, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) @@ -118,10 +121,13 @@ func configureReconcilers(k8sManager manager.Manager, operatorConfig *config.Ope k8sClientSet, err := kubernetes.NewForConfig(k8sManager.GetConfig()) if err != nil { - return fmt.Errorf("unable to create clientset: %w", err) + return fmt.Errorf("unable to create k8s clientset: %w", err) } ecosystemClientSet, err := ecosystem.NewClientSet(k8sManager.GetConfig(), k8sClientSet) + if err != nil { + return fmt.Errorf("unable to create ecosystem clientset: %w", err) + } if err = (controller.NewRestoreReconciler(ecosystemClientSet, eventRecorder, operatorConfig.Namespace)).SetupWithManager(k8sManager); err != nil { return fmt.Errorf("unable to create restore controller: %w", err) From d862d1fc6c3948690974c8ed63d331cff6896c3b Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 11:09:15 +0200 Subject: [PATCH 22/37] #1 Add go doc comments --- pkg/api/ecosystem/ecosystemClientSet.go | 10 ++++++++++ pkg/api/v1/backup_types.go | 4 +++- pkg/api/v1/restore_types.go | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pkg/api/ecosystem/ecosystemClientSet.go b/pkg/api/ecosystem/ecosystemClientSet.go index c47904a..74ef854 100644 --- a/pkg/api/ecosystem/ecosystemClientSet.go +++ b/pkg/api/ecosystem/ecosystemClientSet.go @@ -10,21 +10,26 @@ import ( v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" ) +// Interface extends the kubernetes.Interface to add functionality for handling the custom resources of this operator. type Interface interface { kubernetes.Interface + // EcosystemV1Alpha1 returns a getter for the custom resources of this operator. EcosystemV1Alpha1() V1Alpha1Interface } +// V1Alpha1Interface is a getter for the custom resources of this operator. type V1Alpha1Interface interface { BackupsGetter RestoresGetter } type BackupsGetter interface { + // Backups returns a client for backups in the given namespace. Backups(namespace string) BackupInterface } type RestoresGetter interface { + // Restores returns a client for restores in the given namespace. Restores(namespace string) RestoreInterface } @@ -41,11 +46,13 @@ func NewClientSet(config *rest.Config, clientSet *kubernetes.Clientset) (*Client }, nil } +// ClientSet extends the kubernetes.Interface to add functionality for handling the custom resources of this operator. type ClientSet struct { kubernetes.Interface ecosystemV1Alpha1 V1Alpha1Interface } +// EcosystemV1Alpha1 returns a getter for the custom resources of this operator. func (cs *ClientSet) EcosystemV1Alpha1() V1Alpha1Interface { return cs.ecosystemV1Alpha1 } @@ -75,10 +82,12 @@ func NewForConfig(c *rest.Config) (*V1Alpha1Client, error) { return &V1Alpha1Client{restClient: client}, nil } +// V1Alpha1Client is a getter for the custom resources of this operator. type V1Alpha1Client struct { restClient rest.Interface } +// Backups returns a client for backups in the given namespace. func (brc *V1Alpha1Client) Backups(namespace string) BackupInterface { return &backupClient{ client: brc.restClient, @@ -86,6 +95,7 @@ func (brc *V1Alpha1Client) Backups(namespace string) BackupInterface { } } +// Restores returns a client for restores in the given namespace. func (brc *V1Alpha1Client) Restores(namespace string) RestoreInterface { return &restoreClient{ client: brc.restClient, diff --git a/pkg/api/v1/backup_types.go b/pkg/api/v1/backup_types.go index 85b55dd..598a347 100644 --- a/pkg/api/v1/backup_types.go +++ b/pkg/api/v1/backup_types.go @@ -36,7 +36,9 @@ type Backup struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec BackupSpec `json:"spec,omitempty"` + // Spec defines the desired state of Backup + Spec BackupSpec `json:"spec,omitempty"` + // Status defines the observed state of Backup Status BackupStatus `json:"status,omitempty"` } diff --git a/pkg/api/v1/restore_types.go b/pkg/api/v1/restore_types.go index c1c2c00..d98141d 100644 --- a/pkg/api/v1/restore_types.go +++ b/pkg/api/v1/restore_types.go @@ -36,7 +36,9 @@ type Restore struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec RestoreSpec `json:"spec,omitempty"` + // Spec defines the desired state of Restore + Spec RestoreSpec `json:"spec,omitempty"` + // Status defines the observed state of Restore Status RestoreStatus `json:"status,omitempty"` } From 367500c2ceaf256f0876c3b5ca428a6187ad41df Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 11:32:38 +0200 Subject: [PATCH 23/37] #1 Fix copy-paste error in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d058dae..856519f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # k8s-backup-operator -Cloudogu EcoSystem Dogu operator for Kubernetes +Cloudogu EcoSystem backup operator for Kubernetes --- From 5bf915db34db13cdb421c68feb0bc384dbc63b18 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 11:33:11 +0200 Subject: [PATCH 24/37] #1 Remove TODOs --- config/manager/manager.yaml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index f3bd60b..5531608 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -22,7 +22,7 @@ spec: labels: control-plane: controller-manager spec: - # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # Uncomment the following code to configure the nodeAffinity expression # according to the platforms which are supported by your solution. # It is considered best practice to support multiple architectures. You can # build your manager image using the makefile target docker-buildx. @@ -44,13 +44,8 @@ spec: # - linux securityContext: runAsNonRoot: true - # TODO(user): For common cases that do not require escalating privileges - # it is recommended to ensure that all your Pods/Containers are restrictive. - # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted - # Please uncomment the following code if your project does NOT have to work on old Kubernetes - # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). - # seccompProfile: - # type: RuntimeDefault + seccompProfile: + type: RuntimeDefault containers: - args: - --leader-elect @@ -83,8 +78,6 @@ spec: port: 8081 initialDelaySeconds: 5 periodSeconds: 10 - # TODO(user): Configure the resources accordingly based on the project requirements. - # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: limits: cpu: 500m From 69a9097ce4d0716f362950afc421935856ab6293 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 12:10:32 +0200 Subject: [PATCH 25/37] #1 Test reconcilers --- pkg/controllers/backupReconciler.go | 2 +- pkg/controllers/backupReconciler_test.go | 85 ++ pkg/controllers/interfaces.go | 5 + .../mock_controllerManager_test.go | 786 ++++++++++++++++++ pkg/controllers/restoreReconciler.go | 2 +- pkg/controllers/restoreReconciler_test.go | 68 ++ 6 files changed, 946 insertions(+), 2 deletions(-) create mode 100644 pkg/controllers/backupReconciler_test.go create mode 100644 pkg/controllers/mock_controllerManager_test.go create mode 100644 pkg/controllers/restoreReconciler_test.go diff --git a/pkg/controllers/backupReconciler.go b/pkg/controllers/backupReconciler.go index 4ace1e1..e0e10b7 100644 --- a/pkg/controllers/backupReconciler.go +++ b/pkg/controllers/backupReconciler.go @@ -42,7 +42,7 @@ func (r *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } // SetupWithManager sets up the controller with the Manager. -func (r *backupReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *backupReconciler) SetupWithManager(mgr controllerManager) error { return ctrl.NewControllerManagedBy(mgr). For(&k8sv1.Backup{}). Complete(r) diff --git a/pkg/controllers/backupReconciler_test.go b/pkg/controllers/backupReconciler_test.go new file mode 100644 index 0000000..59d975f --- /dev/null +++ b/pkg/controllers/backupReconciler_test.go @@ -0,0 +1,85 @@ +package controller + +import ( + "context" + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/config" + "sigs.k8s.io/controller-runtime/pkg/log" + "testing" +) + +var testCtx = context.TODO() + +func TestNewBackupReconciler(t *testing.T) { + t.Run("should create backup reconciler", func(t *testing.T) { + // when + actual := NewBackupReconciler(nil, nil, "default") + + // then + assert.NotNil(t, actual) + }) +} + +func Test_backupReconciler_Reconcile(t *testing.T) { + t.Run("should succeed", func(t *testing.T) { + // given + request := ctrl.Request{} + sut := &backupReconciler{} + + // when + actual, err := sut.Reconcile(testCtx, request) + + // then + require.NoError(t, err) + assert.Equal(t, ctrl.Result{}, actual) + }) +} + +func Test_backupReconciler_SetupWithManager(t *testing.T) { + t.Run("should fail", func(t *testing.T) { + // given + sut := &backupReconciler{} + + // when + err := sut.SetupWithManager(nil) + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "must provide a non-nil Manager") + }) + t.Run("should succeed", func(t *testing.T) { + // given + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + logger := log.FromContext(testCtx) + ctrlManMock.EXPECT().GetLogger().Return(logger) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + + sut := &backupReconciler{} + + // when + err := sut.SetupWithManager(ctrlManMock) + + // then + require.NoError(t, err) + }) +} + +func createScheme(t *testing.T) *runtime.Scheme { + t.Helper() + + scheme := runtime.NewScheme() + gv, err := schema.ParseGroupVersion("k8s.cloudogu.com/v1") + assert.NoError(t, err) + + scheme.AddKnownTypes(gv, &v1.Backup{}, &v1.Restore{}) + return scheme +} diff --git a/pkg/controllers/interfaces.go b/pkg/controllers/interfaces.go index 779f89a..8478df4 100644 --- a/pkg/controllers/interfaces.go +++ b/pkg/controllers/interfaces.go @@ -2,6 +2,7 @@ package controller import ( "k8s.io/client-go/tools/record" + ctrl "sigs.k8s.io/controller-runtime" "github.com/cloudogu/k8s-backup-operator/pkg/api/ecosystem" ) @@ -13,3 +14,7 @@ type ecosystemInterface interface { type eventRecorder interface { record.EventRecorder } + +type controllerManager interface { + ctrl.Manager +} diff --git a/pkg/controllers/mock_controllerManager_test.go b/pkg/controllers/mock_controllerManager_test.go new file mode 100644 index 0000000..81dc075 --- /dev/null +++ b/pkg/controllers/mock_controllerManager_test.go @@ -0,0 +1,786 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package controller + +import ( + cache "sigs.k8s.io/controller-runtime/pkg/cache" + client "sigs.k8s.io/controller-runtime/pkg/client" + + config "sigs.k8s.io/controller-runtime/pkg/config" + + context "context" + + healthz "sigs.k8s.io/controller-runtime/pkg/healthz" + + http "net/http" + + logr "github.com/go-logr/logr" + + manager "sigs.k8s.io/controller-runtime/pkg/manager" + + meta "k8s.io/apimachinery/pkg/api/meta" + + mock "github.com/stretchr/testify/mock" + + record "k8s.io/client-go/tools/record" + + rest "k8s.io/client-go/rest" + + runtime "k8s.io/apimachinery/pkg/runtime" + + webhook "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// mockControllerManager is an autogenerated mock type for the controllerManager type +type mockControllerManager struct { + mock.Mock +} + +type mockControllerManager_Expecter struct { + mock *mock.Mock +} + +func (_m *mockControllerManager) EXPECT() *mockControllerManager_Expecter { + return &mockControllerManager_Expecter{mock: &_m.Mock} +} + +// Add provides a mock function with given fields: _a0 +func (_m *mockControllerManager) Add(_a0 manager.Runnable) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(manager.Runnable) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' +type mockControllerManager_Add_Call struct { + *mock.Call +} + +// Add is a helper method to define mock.On call +// - _a0 manager.Runnable +func (_e *mockControllerManager_Expecter) Add(_a0 interface{}) *mockControllerManager_Add_Call { + return &mockControllerManager_Add_Call{Call: _e.mock.On("Add", _a0)} +} + +func (_c *mockControllerManager_Add_Call) Run(run func(_a0 manager.Runnable)) *mockControllerManager_Add_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(manager.Runnable)) + }) + return _c +} + +func (_c *mockControllerManager_Add_Call) Return(_a0 error) *mockControllerManager_Add_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Add_Call) RunAndReturn(run func(manager.Runnable) error) *mockControllerManager_Add_Call { + _c.Call.Return(run) + return _c +} + +// AddHealthzCheck provides a mock function with given fields: name, check +func (_m *mockControllerManager) AddHealthzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_AddHealthzCheck_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddHealthzCheck' +type mockControllerManager_AddHealthzCheck_Call struct { + *mock.Call +} + +// AddHealthzCheck is a helper method to define mock.On call +// - name string +// - check healthz.Checker +func (_e *mockControllerManager_Expecter) AddHealthzCheck(name interface{}, check interface{}) *mockControllerManager_AddHealthzCheck_Call { + return &mockControllerManager_AddHealthzCheck_Call{Call: _e.mock.On("AddHealthzCheck", name, check)} +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) Run(run func(name string, check healthz.Checker)) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(healthz.Checker)) + }) + return _c +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) Return(_a0 error) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) RunAndReturn(run func(string, healthz.Checker) error) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Return(run) + return _c +} + +// AddReadyzCheck provides a mock function with given fields: name, check +func (_m *mockControllerManager) AddReadyzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_AddReadyzCheck_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddReadyzCheck' +type mockControllerManager_AddReadyzCheck_Call struct { + *mock.Call +} + +// AddReadyzCheck is a helper method to define mock.On call +// - name string +// - check healthz.Checker +func (_e *mockControllerManager_Expecter) AddReadyzCheck(name interface{}, check interface{}) *mockControllerManager_AddReadyzCheck_Call { + return &mockControllerManager_AddReadyzCheck_Call{Call: _e.mock.On("AddReadyzCheck", name, check)} +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) Run(run func(name string, check healthz.Checker)) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(healthz.Checker)) + }) + return _c +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) Return(_a0 error) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) RunAndReturn(run func(string, healthz.Checker) error) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Return(run) + return _c +} + +// Elected provides a mock function with given fields: +func (_m *mockControllerManager) Elected() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// mockControllerManager_Elected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Elected' +type mockControllerManager_Elected_Call struct { + *mock.Call +} + +// Elected is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) Elected() *mockControllerManager_Elected_Call { + return &mockControllerManager_Elected_Call{Call: _e.mock.On("Elected")} +} + +func (_c *mockControllerManager_Elected_Call) Run(run func()) *mockControllerManager_Elected_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_Elected_Call) Return(_a0 <-chan struct{}) *mockControllerManager_Elected_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Elected_Call) RunAndReturn(run func() <-chan struct{}) *mockControllerManager_Elected_Call { + _c.Call.Return(run) + return _c +} + +// GetAPIReader provides a mock function with given fields: +func (_m *mockControllerManager) GetAPIReader() client.Reader { + ret := _m.Called() + + var r0 client.Reader + if rf, ok := ret.Get(0).(func() client.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Reader) + } + } + + return r0 +} + +// mockControllerManager_GetAPIReader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAPIReader' +type mockControllerManager_GetAPIReader_Call struct { + *mock.Call +} + +// GetAPIReader is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetAPIReader() *mockControllerManager_GetAPIReader_Call { + return &mockControllerManager_GetAPIReader_Call{Call: _e.mock.On("GetAPIReader")} +} + +func (_c *mockControllerManager_GetAPIReader_Call) Run(run func()) *mockControllerManager_GetAPIReader_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetAPIReader_Call) Return(_a0 client.Reader) *mockControllerManager_GetAPIReader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetAPIReader_Call) RunAndReturn(run func() client.Reader) *mockControllerManager_GetAPIReader_Call { + _c.Call.Return(run) + return _c +} + +// GetCache provides a mock function with given fields: +func (_m *mockControllerManager) GetCache() cache.Cache { + ret := _m.Called() + + var r0 cache.Cache + if rf, ok := ret.Get(0).(func() cache.Cache); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.Cache) + } + } + + return r0 +} + +// mockControllerManager_GetCache_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCache' +type mockControllerManager_GetCache_Call struct { + *mock.Call +} + +// GetCache is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetCache() *mockControllerManager_GetCache_Call { + return &mockControllerManager_GetCache_Call{Call: _e.mock.On("GetCache")} +} + +func (_c *mockControllerManager_GetCache_Call) Run(run func()) *mockControllerManager_GetCache_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetCache_Call) Return(_a0 cache.Cache) *mockControllerManager_GetCache_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetCache_Call) RunAndReturn(run func() cache.Cache) *mockControllerManager_GetCache_Call { + _c.Call.Return(run) + return _c +} + +// GetClient provides a mock function with given fields: +func (_m *mockControllerManager) GetClient() client.Client { + ret := _m.Called() + + var r0 client.Client + if rf, ok := ret.Get(0).(func() client.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Client) + } + } + + return r0 +} + +// mockControllerManager_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' +type mockControllerManager_GetClient_Call struct { + *mock.Call +} + +// GetClient is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetClient() *mockControllerManager_GetClient_Call { + return &mockControllerManager_GetClient_Call{Call: _e.mock.On("GetClient")} +} + +func (_c *mockControllerManager_GetClient_Call) Run(run func()) *mockControllerManager_GetClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetClient_Call) Return(_a0 client.Client) *mockControllerManager_GetClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetClient_Call) RunAndReturn(run func() client.Client) *mockControllerManager_GetClient_Call { + _c.Call.Return(run) + return _c +} + +// GetConfig provides a mock function with given fields: +func (_m *mockControllerManager) GetConfig() *rest.Config { + ret := _m.Called() + + var r0 *rest.Config + if rf, ok := ret.Get(0).(func() *rest.Config); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Config) + } + } + + return r0 +} + +// mockControllerManager_GetConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetConfig' +type mockControllerManager_GetConfig_Call struct { + *mock.Call +} + +// GetConfig is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetConfig() *mockControllerManager_GetConfig_Call { + return &mockControllerManager_GetConfig_Call{Call: _e.mock.On("GetConfig")} +} + +func (_c *mockControllerManager_GetConfig_Call) Run(run func()) *mockControllerManager_GetConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetConfig_Call) Return(_a0 *rest.Config) *mockControllerManager_GetConfig_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetConfig_Call) RunAndReturn(run func() *rest.Config) *mockControllerManager_GetConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetControllerOptions provides a mock function with given fields: +func (_m *mockControllerManager) GetControllerOptions() config.Controller { + ret := _m.Called() + + var r0 config.Controller + if rf, ok := ret.Get(0).(func() config.Controller); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(config.Controller) + } + + return r0 +} + +// mockControllerManager_GetControllerOptions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetControllerOptions' +type mockControllerManager_GetControllerOptions_Call struct { + *mock.Call +} + +// GetControllerOptions is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetControllerOptions() *mockControllerManager_GetControllerOptions_Call { + return &mockControllerManager_GetControllerOptions_Call{Call: _e.mock.On("GetControllerOptions")} +} + +func (_c *mockControllerManager_GetControllerOptions_Call) Run(run func()) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetControllerOptions_Call) Return(_a0 config.Controller) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetControllerOptions_Call) RunAndReturn(run func() config.Controller) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Return(run) + return _c +} + +// GetEventRecorderFor provides a mock function with given fields: name +func (_m *mockControllerManager) GetEventRecorderFor(name string) record.EventRecorder { + ret := _m.Called(name) + + var r0 record.EventRecorder + if rf, ok := ret.Get(0).(func(string) record.EventRecorder); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(record.EventRecorder) + } + } + + return r0 +} + +// mockControllerManager_GetEventRecorderFor_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventRecorderFor' +type mockControllerManager_GetEventRecorderFor_Call struct { + *mock.Call +} + +// GetEventRecorderFor is a helper method to define mock.On call +// - name string +func (_e *mockControllerManager_Expecter) GetEventRecorderFor(name interface{}) *mockControllerManager_GetEventRecorderFor_Call { + return &mockControllerManager_GetEventRecorderFor_Call{Call: _e.mock.On("GetEventRecorderFor", name)} +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) Run(run func(name string)) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) Return(_a0 record.EventRecorder) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) RunAndReturn(run func(string) record.EventRecorder) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Return(run) + return _c +} + +// GetFieldIndexer provides a mock function with given fields: +func (_m *mockControllerManager) GetFieldIndexer() client.FieldIndexer { + ret := _m.Called() + + var r0 client.FieldIndexer + if rf, ok := ret.Get(0).(func() client.FieldIndexer); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.FieldIndexer) + } + } + + return r0 +} + +// mockControllerManager_GetFieldIndexer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFieldIndexer' +type mockControllerManager_GetFieldIndexer_Call struct { + *mock.Call +} + +// GetFieldIndexer is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetFieldIndexer() *mockControllerManager_GetFieldIndexer_Call { + return &mockControllerManager_GetFieldIndexer_Call{Call: _e.mock.On("GetFieldIndexer")} +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) Run(run func()) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) Return(_a0 client.FieldIndexer) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) RunAndReturn(run func() client.FieldIndexer) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Return(run) + return _c +} + +// GetHTTPClient provides a mock function with given fields: +func (_m *mockControllerManager) GetHTTPClient() *http.Client { + ret := _m.Called() + + var r0 *http.Client + if rf, ok := ret.Get(0).(func() *http.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Client) + } + } + + return r0 +} + +// mockControllerManager_GetHTTPClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHTTPClient' +type mockControllerManager_GetHTTPClient_Call struct { + *mock.Call +} + +// GetHTTPClient is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetHTTPClient() *mockControllerManager_GetHTTPClient_Call { + return &mockControllerManager_GetHTTPClient_Call{Call: _e.mock.On("GetHTTPClient")} +} + +func (_c *mockControllerManager_GetHTTPClient_Call) Run(run func()) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetHTTPClient_Call) Return(_a0 *http.Client) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetHTTPClient_Call) RunAndReturn(run func() *http.Client) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Return(run) + return _c +} + +// GetLogger provides a mock function with given fields: +func (_m *mockControllerManager) GetLogger() logr.Logger { + ret := _m.Called() + + var r0 logr.Logger + if rf, ok := ret.Get(0).(func() logr.Logger); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(logr.Logger) + } + + return r0 +} + +// mockControllerManager_GetLogger_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLogger' +type mockControllerManager_GetLogger_Call struct { + *mock.Call +} + +// GetLogger is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetLogger() *mockControllerManager_GetLogger_Call { + return &mockControllerManager_GetLogger_Call{Call: _e.mock.On("GetLogger")} +} + +func (_c *mockControllerManager_GetLogger_Call) Run(run func()) *mockControllerManager_GetLogger_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetLogger_Call) Return(_a0 logr.Logger) *mockControllerManager_GetLogger_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetLogger_Call) RunAndReturn(run func() logr.Logger) *mockControllerManager_GetLogger_Call { + _c.Call.Return(run) + return _c +} + +// GetRESTMapper provides a mock function with given fields: +func (_m *mockControllerManager) GetRESTMapper() meta.RESTMapper { + ret := _m.Called() + + var r0 meta.RESTMapper + if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(meta.RESTMapper) + } + } + + return r0 +} + +// mockControllerManager_GetRESTMapper_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRESTMapper' +type mockControllerManager_GetRESTMapper_Call struct { + *mock.Call +} + +// GetRESTMapper is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetRESTMapper() *mockControllerManager_GetRESTMapper_Call { + return &mockControllerManager_GetRESTMapper_Call{Call: _e.mock.On("GetRESTMapper")} +} + +func (_c *mockControllerManager_GetRESTMapper_Call) Run(run func()) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetRESTMapper_Call) Return(_a0 meta.RESTMapper) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetRESTMapper_Call) RunAndReturn(run func() meta.RESTMapper) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Return(run) + return _c +} + +// GetScheme provides a mock function with given fields: +func (_m *mockControllerManager) GetScheme() *runtime.Scheme { + ret := _m.Called() + + var r0 *runtime.Scheme + if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.Scheme) + } + } + + return r0 +} + +// mockControllerManager_GetScheme_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetScheme' +type mockControllerManager_GetScheme_Call struct { + *mock.Call +} + +// GetScheme is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetScheme() *mockControllerManager_GetScheme_Call { + return &mockControllerManager_GetScheme_Call{Call: _e.mock.On("GetScheme")} +} + +func (_c *mockControllerManager_GetScheme_Call) Run(run func()) *mockControllerManager_GetScheme_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetScheme_Call) Return(_a0 *runtime.Scheme) *mockControllerManager_GetScheme_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetScheme_Call) RunAndReturn(run func() *runtime.Scheme) *mockControllerManager_GetScheme_Call { + _c.Call.Return(run) + return _c +} + +// GetWebhookServer provides a mock function with given fields: +func (_m *mockControllerManager) GetWebhookServer() webhook.Server { + ret := _m.Called() + + var r0 webhook.Server + if rf, ok := ret.Get(0).(func() webhook.Server); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(webhook.Server) + } + } + + return r0 +} + +// mockControllerManager_GetWebhookServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWebhookServer' +type mockControllerManager_GetWebhookServer_Call struct { + *mock.Call +} + +// GetWebhookServer is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetWebhookServer() *mockControllerManager_GetWebhookServer_Call { + return &mockControllerManager_GetWebhookServer_Call{Call: _e.mock.On("GetWebhookServer")} +} + +func (_c *mockControllerManager_GetWebhookServer_Call) Run(run func()) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetWebhookServer_Call) Return(_a0 webhook.Server) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetWebhookServer_Call) RunAndReturn(run func() webhook.Server) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: ctx +func (_m *mockControllerManager) Start(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type mockControllerManager_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - ctx context.Context +func (_e *mockControllerManager_Expecter) Start(ctx interface{}) *mockControllerManager_Start_Call { + return &mockControllerManager_Start_Call{Call: _e.mock.On("Start", ctx)} +} + +func (_c *mockControllerManager_Start_Call) Run(run func(ctx context.Context)) *mockControllerManager_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockControllerManager_Start_Call) Return(_a0 error) *mockControllerManager_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Start_Call) RunAndReturn(run func(context.Context) error) *mockControllerManager_Start_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockControllerManager interface { + mock.TestingT + Cleanup(func()) +} + +// newMockControllerManager creates a new instance of mockControllerManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockControllerManager(t mockConstructorTestingTnewMockControllerManager) *mockControllerManager { + mock := &mockControllerManager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/controllers/restoreReconciler.go b/pkg/controllers/restoreReconciler.go index 50b3a2f..6aed424 100644 --- a/pkg/controllers/restoreReconciler.go +++ b/pkg/controllers/restoreReconciler.go @@ -41,7 +41,7 @@ func (r *restoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct } // SetupWithManager sets up the controller with the Manager. -func (r *restoreReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *restoreReconciler) SetupWithManager(mgr controllerManager) error { return ctrl.NewControllerManagedBy(mgr). For(&k8sv1.Restore{}). Complete(r) diff --git a/pkg/controllers/restoreReconciler_test.go b/pkg/controllers/restoreReconciler_test.go new file mode 100644 index 0000000..de68956 --- /dev/null +++ b/pkg/controllers/restoreReconciler_test.go @@ -0,0 +1,68 @@ +package controller + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/config" + "sigs.k8s.io/controller-runtime/pkg/log" + "testing" +) + +func TestNewRestoreReconciler(t *testing.T) { + t.Run("should create restore reconciler", func(t *testing.T) { + // when + actual := NewRestoreReconciler(nil, nil, "default") + + // then + assert.NotNil(t, actual) + }) +} + +func Test_restoreReconciler_Reconcile(t *testing.T) { + t.Run("should succeed", func(t *testing.T) { + // given + request := ctrl.Request{} + sut := &restoreReconciler{} + + // when + actual, err := sut.Reconcile(testCtx, request) + + // then + require.NoError(t, err) + assert.Equal(t, ctrl.Result{}, actual) + }) +} + +func Test_restoreReconciler_SetupWithManager(t *testing.T) { + t.Run("should fail", func(t *testing.T) { + // given + sut := &restoreReconciler{} + + // when + err := sut.SetupWithManager(nil) + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "must provide a non-nil Manager") + }) + t.Run("should succeed", func(t *testing.T) { + // given + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + logger := log.FromContext(testCtx) + ctrlManMock.EXPECT().GetLogger().Return(logger) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + + sut := &restoreReconciler{} + + // when + err := sut.SetupWithManager(ctrlManMock) + + // then + require.NoError(t, err) + }) +} From ff512268db9512d1f05c0345a29e846b9dffaaf8 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 12:40:54 +0200 Subject: [PATCH 26/37] #1 Test operator config --- pkg/config/config.go | 4 +- pkg/config/config_test.go | 85 +++++++++ pkg/config/mock_logSink_test.go | 298 ++++++++++++++++++++++++++++++++ 3 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 pkg/config/config_test.go create mode 100644 pkg/config/mock_logSink_test.go diff --git a/pkg/config/config.go b/pkg/config/config.go index 7ae54e3..e476c5b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -75,9 +75,9 @@ func getNamespace() (string, error) { } func getEnvVar(name string) (string, error) { - ns, found := os.LookupEnv(name) + env, found := os.LookupEnv(name) if !found { return "", fmt.Errorf("environment variable %s must be set", name) } - return ns, nil + return env, nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 0000000..f63ad13 --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,85 @@ +package config + +import ( + "github.com/Masterminds/semver/v3" + "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "os" + "testing" +) + +func TestNewOperatorConfig(t *testing.T) { + t.Run("should fail to read stage and parse version", func(t *testing.T) { + // given + t.Setenv(StageEnvVar, "") + err := os.Unsetenv(StageEnvVar) + require.NoError(t, err) + + oldLog := log + defer func() { log = oldLog }() + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().Error(mock.Anything, "Error reading stage environment variable. Use stage production").Return() + log = logr.New(logMock) + + // when + actual, err := NewOperatorConfig("not-semver") + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "failed to parse version") + assert.Nil(t, actual) + }) + t.Run("should use development stage and fail to get namespace", func(t *testing.T) { + // given + t.Setenv(StageEnvVar, StageDevelopment) + t.Setenv(namespaceEnvVar, "") + err := os.Unsetenv(namespaceEnvVar) + require.NoError(t, err) + + oldLog := log + defer func() { log = oldLog }() + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().Enabled(0).Return(true) + logMock.EXPECT().Info(0, "Version: [0.1.0]").Return() + logMock.EXPECT().Info(0, "Starting in development mode! This is not recommended for production!").Return() + log = logr.New(logMock) + + // when + actual, err := NewOperatorConfig("0.1.0") + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "failed to read namespace: failed to get env var [NAMESPACE]: environment variable NAMESPACE must be set") + assert.Nil(t, actual) + }) + t.Run("should use development stage and succeed", func(t *testing.T) { + // given + t.Setenv(StageEnvVar, StageDevelopment) + t.Setenv(namespaceEnvVar, "ecosystem") + + oldLog := log + defer func() { log = oldLog }() + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().Enabled(0).Return(true) + logMock.EXPECT().Info(0, "Version: [0.1.0]").Return() + logMock.EXPECT().Info(0, "Starting in development mode! This is not recommended for production!").Return() + logMock.EXPECT().Info(0, "Deploying the k8s dogu operator in namespace ecosystem").Return() + log = logr.New(logMock) + + // when + actual, err := NewOperatorConfig("0.1.0") + + // then + require.NoError(t, err) + expected := &OperatorConfig{ + Version: semver.MustParse("0.1.0"), + Namespace: "ecosystem", + } + assert.Equal(t, expected, actual) + }) +} diff --git a/pkg/config/mock_logSink_test.go b/pkg/config/mock_logSink_test.go new file mode 100644 index 0000000..8fcf095 --- /dev/null +++ b/pkg/config/mock_logSink_test.go @@ -0,0 +1,298 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package config + +import ( + logr "github.com/go-logr/logr" + mock "github.com/stretchr/testify/mock" +) + +// mockLogSink is an autogenerated mock type for the logSink type +type mockLogSink struct { + mock.Mock +} + +type mockLogSink_Expecter struct { + mock *mock.Mock +} + +func (_m *mockLogSink) EXPECT() *mockLogSink_Expecter { + return &mockLogSink_Expecter{mock: &_m.Mock} +} + +// Enabled provides a mock function with given fields: level +func (_m *mockLogSink) Enabled(level int) bool { + ret := _m.Called(level) + + var r0 bool + if rf, ok := ret.Get(0).(func(int) bool); ok { + r0 = rf(level) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// mockLogSink_Enabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Enabled' +type mockLogSink_Enabled_Call struct { + *mock.Call +} + +// Enabled is a helper method to define mock.On call +// - level int +func (_e *mockLogSink_Expecter) Enabled(level interface{}) *mockLogSink_Enabled_Call { + return &mockLogSink_Enabled_Call{Call: _e.mock.On("Enabled", level)} +} + +func (_c *mockLogSink_Enabled_Call) Run(run func(level int)) *mockLogSink_Enabled_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *mockLogSink_Enabled_Call) Return(_a0 bool) *mockLogSink_Enabled_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_Enabled_Call) RunAndReturn(run func(int) bool) *mockLogSink_Enabled_Call { + _c.Call.Return(run) + return _c +} + +// Error provides a mock function with given fields: err, msg, keysAndValues +func (_m *mockLogSink) Error(err error, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, err, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// mockLogSink_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error' +type mockLogSink_Error_Call struct { + *mock.Call +} + +// Error is a helper method to define mock.On call +// - err error +// - msg string +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) Error(err interface{}, msg interface{}, keysAndValues ...interface{}) *mockLogSink_Error_Call { + return &mockLogSink_Error_Call{Call: _e.mock.On("Error", + append([]interface{}{err, msg}, keysAndValues...)...)} +} + +func (_c *mockLogSink_Error_Call) Run(run func(err error, msg string, keysAndValues ...interface{})) *mockLogSink_Error_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(error), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_Error_Call) Return() *mockLogSink_Error_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Error_Call) RunAndReturn(run func(error, string, ...interface{})) *mockLogSink_Error_Call { + _c.Call.Return(run) + return _c +} + +// Info provides a mock function with given fields: level, msg, keysAndValues +func (_m *mockLogSink) Info(level int, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, level, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// mockLogSink_Info_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Info' +type mockLogSink_Info_Call struct { + *mock.Call +} + +// Info is a helper method to define mock.On call +// - level int +// - msg string +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) Info(level interface{}, msg interface{}, keysAndValues ...interface{}) *mockLogSink_Info_Call { + return &mockLogSink_Info_Call{Call: _e.mock.On("Info", + append([]interface{}{level, msg}, keysAndValues...)...)} +} + +func (_c *mockLogSink_Info_Call) Run(run func(level int, msg string, keysAndValues ...interface{})) *mockLogSink_Info_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(int), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_Info_Call) Return() *mockLogSink_Info_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Info_Call) RunAndReturn(run func(int, string, ...interface{})) *mockLogSink_Info_Call { + _c.Call.Return(run) + return _c +} + +// Init provides a mock function with given fields: info +func (_m *mockLogSink) Init(info logr.RuntimeInfo) { + _m.Called(info) +} + +// mockLogSink_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init' +type mockLogSink_Init_Call struct { + *mock.Call +} + +// Init is a helper method to define mock.On call +// - info logr.RuntimeInfo +func (_e *mockLogSink_Expecter) Init(info interface{}) *mockLogSink_Init_Call { + return &mockLogSink_Init_Call{Call: _e.mock.On("Init", info)} +} + +func (_c *mockLogSink_Init_Call) Run(run func(info logr.RuntimeInfo)) *mockLogSink_Init_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(logr.RuntimeInfo)) + }) + return _c +} + +func (_c *mockLogSink_Init_Call) Return() *mockLogSink_Init_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Init_Call) RunAndReturn(run func(logr.RuntimeInfo)) *mockLogSink_Init_Call { + _c.Call.Return(run) + return _c +} + +// WithName provides a mock function with given fields: name +func (_m *mockLogSink) WithName(name string) logr.LogSink { + ret := _m.Called(name) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(string) logr.LogSink); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +// mockLogSink_WithName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithName' +type mockLogSink_WithName_Call struct { + *mock.Call +} + +// WithName is a helper method to define mock.On call +// - name string +func (_e *mockLogSink_Expecter) WithName(name interface{}) *mockLogSink_WithName_Call { + return &mockLogSink_WithName_Call{Call: _e.mock.On("WithName", name)} +} + +func (_c *mockLogSink_WithName_Call) Run(run func(name string)) *mockLogSink_WithName_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockLogSink_WithName_Call) Return(_a0 logr.LogSink) *mockLogSink_WithName_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_WithName_Call) RunAndReturn(run func(string) logr.LogSink) *mockLogSink_WithName_Call { + _c.Call.Return(run) + return _c +} + +// WithValues provides a mock function with given fields: keysAndValues +func (_m *mockLogSink) WithValues(keysAndValues ...interface{}) logr.LogSink { + var _ca []interface{} + _ca = append(_ca, keysAndValues...) + ret := _m.Called(_ca...) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(...interface{}) logr.LogSink); ok { + r0 = rf(keysAndValues...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +// mockLogSink_WithValues_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithValues' +type mockLogSink_WithValues_Call struct { + *mock.Call +} + +// WithValues is a helper method to define mock.On call +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) WithValues(keysAndValues ...interface{}) *mockLogSink_WithValues_Call { + return &mockLogSink_WithValues_Call{Call: _e.mock.On("WithValues", + append([]interface{}{}, keysAndValues...)...)} +} + +func (_c *mockLogSink_WithValues_Call) Run(run func(keysAndValues ...interface{})) *mockLogSink_WithValues_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_WithValues_Call) Return(_a0 logr.LogSink) *mockLogSink_WithValues_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_WithValues_Call) RunAndReturn(run func(...interface{}) logr.LogSink) *mockLogSink_WithValues_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockLogSink interface { + mock.TestingT + Cleanup(func()) +} + +// newMockLogSink creates a new instance of mockLogSink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockLogSink(t mockConstructorTestingTnewMockLogSink) *mockLogSink { + mock := &mockLogSink{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From b4114bea4aefbef1dc2d6ca3bd2159aec1d86582 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 15:42:17 +0200 Subject: [PATCH 27/37] #1 Test main --- main.go | 33 +- main_internal_test.go | 311 +++++++++++++ mock_controllerManager_test.go | 786 +++++++++++++++++++++++++++++++++ mock_eventRecorder_test.go | 167 +++++++ mock_logSink_test.go | 298 +++++++++++++ 5 files changed, 1583 insertions(+), 12 deletions(-) create mode 100644 main_internal_test.go create mode 100644 mock_controllerManager_test.go create mode 100644 mock_eventRecorder_test.go create mode 100644 mock_logSink_test.go diff --git a/main.go b/main.go index 6bbc6f2..56f87a7 100644 --- a/main.go +++ b/main.go @@ -87,6 +87,23 @@ func configureManager(k8sManager manager.Manager, operatorConfig *config.Operato } func getK8sManagerOptions(operatorConfig *config.OperatorConfig) ctrl.Options { + controllerOpts := ctrl.Options{ + Scheme: scheme, + Cache: cache.Options{DefaultNamespaces: map[string]cache.Config{ + operatorConfig.Namespace: {}, + }}, + WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), + LeaderElectionID: "e3f6c1a7.cloudogu.com", + } + zapOpts := zap.Options{} + controllerOpts, zapOpts = parseFlags(controllerOpts) + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zapOpts))) + + return controllerOpts +} + +var parseFlags = func(options ctrl.Options) (ctrl.Options, zap.Options) { var metricsAddr string var enableLeaderElection bool var probeAddr string @@ -101,19 +118,11 @@ func getK8sManagerOptions(operatorConfig *config.OperatorConfig) ctrl.Options { opts.BindFlags(flag.CommandLine) flag.Parse() - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + options.Metrics = server.Options{BindAddress: metricsAddr} + options.HealthProbeBindAddress = probeAddr + options.LeaderElection = enableLeaderElection - return ctrl.Options{ - Scheme: scheme, - Metrics: server.Options{BindAddress: metricsAddr}, - Cache: cache.Options{DefaultNamespaces: map[string]cache.Config{ - operatorConfig.Namespace: {}, - }}, - WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "e3f6c1a7.cloudogu.com", - } + return options, opts } func configureReconcilers(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { diff --git a/main_internal_test.go b/main_internal_test.go new file mode 100644 index 0000000..9c58c1f --- /dev/null +++ b/main_internal_test.go @@ -0,0 +1,311 @@ +package main + +import ( + "context" + "github.com/go-logr/logr" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "testing" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/config" + "sigs.k8s.io/controller-runtime/pkg/manager" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" +) + +var testCtx = context.Background() + +func Test_startOperator(t *testing.T) { + oldParseFlagsFunc := parseFlags + defer func() { parseFlags = oldParseFlagsFunc }() + parseFlags = func(options ctrl.Options) (ctrl.Options, zap.Options) { + return options, zap.Options{Development: true} + } + + t.Run("should fail to create operator config", func(t *testing.T) { + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "unable to create operator config") + }) + t.Run("should fail to create controller manager", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + }() + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return nil, assert.AnError + } + ctrl.GetConfigOrDie = func() *rest.Config { + return &rest.Config{} + } + + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorIs(t, err, assert.AnError) + assert.ErrorContains(t, err, "unable to start manager") + }) + t.Run("should fail to configure reconciler", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + }() + + restConfig := &rest.Config{} + recorderMock := newMockEventRecorder(t) + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetEventRecorderFor("k8s-backup-operator").Return(recorderMock) + ctrlManMock.EXPECT().GetConfig().Return(restConfig) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(runtime.NewScheme()) + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return ctrlManMock, nil + } + ctrl.GetConfigOrDie = func() *rest.Config { + return restConfig + } + + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "unable to configure manager: unable to configure reconciler") + }) + t.Run("should fail to add health check to controller manager", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + oldLog := setupLog + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + setupLog = oldLog + }() + + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().WithValues(mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().WithValues(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(logMock) + setupLog = logr.New(logMock) + + restConfig := &rest.Config{} + recorderMock := newMockEventRecorder(t) + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetEventRecorderFor("k8s-backup-operator").Return(recorderMock) + ctrlManMock.EXPECT().GetConfig().Return(restConfig) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + ctrlManMock.EXPECT().GetLogger().Return(logr.New(logMock)) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + ctrlManMock.EXPECT().AddHealthzCheck("healthz", mock.Anything).Return(assert.AnError) + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return ctrlManMock, nil + } + ctrl.GetConfigOrDie = func() *rest.Config { + return restConfig + } + + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorIs(t, err, assert.AnError) + assert.ErrorContains(t, err, "unable to configure manager: unable to add checks to the manager: unable to set up health check") + }) + t.Run("should fail to add readiness check to controller manager", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + oldLog := setupLog + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + setupLog = oldLog + }() + + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().WithValues(mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().WithValues(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(logMock) + setupLog = logr.New(logMock) + + restConfig := &rest.Config{} + recorderMock := newMockEventRecorder(t) + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetEventRecorderFor("k8s-backup-operator").Return(recorderMock) + ctrlManMock.EXPECT().GetConfig().Return(restConfig) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + ctrlManMock.EXPECT().GetLogger().Return(logr.New(logMock)) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + ctrlManMock.EXPECT().AddHealthzCheck("healthz", mock.Anything).Return(nil) + ctrlManMock.EXPECT().AddReadyzCheck("readyz", mock.Anything).Return(assert.AnError) + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return ctrlManMock, nil + } + ctrl.GetConfigOrDie = func() *rest.Config { + return restConfig + } + + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorIs(t, err, assert.AnError) + assert.ErrorContains(t, err, "unable to configure manager: unable to add checks to the manager: unable to set up ready check") + }) + t.Run("should fail to start controller manager", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + oldLog := setupLog + oldSignalHandlerFunc := ctrl.SetupSignalHandler + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + setupLog = oldLog + ctrl.SetupSignalHandler = oldSignalHandlerFunc + }() + + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().WithValues(mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().WithValues(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().Enabled(0).Return(true) + logMock.EXPECT().Info(0, "starting manager").Return() + setupLog = logr.New(logMock) + + restConfig := &rest.Config{} + recorderMock := newMockEventRecorder(t) + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetEventRecorderFor("k8s-backup-operator").Return(recorderMock) + ctrlManMock.EXPECT().GetConfig().Return(restConfig) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + ctrlManMock.EXPECT().GetLogger().Return(logr.New(logMock)) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + ctrlManMock.EXPECT().AddHealthzCheck("healthz", mock.Anything).Return(nil) + ctrlManMock.EXPECT().AddReadyzCheck("readyz", mock.Anything).Return(nil) + ctrlManMock.EXPECT().Start(mock.Anything).Return(assert.AnError) + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return ctrlManMock, nil + } + ctrl.GetConfigOrDie = func() *rest.Config { + return restConfig + } + ctrl.SetupSignalHandler = func() context.Context { + return testCtx + } + + // when + err := startOperator() + + // then + require.Error(t, err) + assert.ErrorIs(t, err, assert.AnError) + assert.ErrorContains(t, err, "problem running manager") + }) + t.Run("should succeed to start controller manager", func(t *testing.T) { + // given + t.Setenv("NAMESPACE", "ecosystem") + + oldNewManagerFunc := ctrl.NewManager + oldGetConfigFunc := ctrl.GetConfigOrDie + oldLog := setupLog + oldSignalHandlerFunc := ctrl.SetupSignalHandler + defer func() { + ctrl.NewManager = oldNewManagerFunc + ctrl.GetConfigOrDie = oldGetConfigFunc + setupLog = oldLog + ctrl.SetupSignalHandler = oldSignalHandlerFunc + }() + + logMock := newMockLogSink(t) + logMock.EXPECT().Init(mock.Anything).Return() + logMock.EXPECT().WithValues(mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().WithValues(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(logMock) + logMock.EXPECT().Enabled(0).Return(true) + logMock.EXPECT().Info(0, "starting manager").Return() + setupLog = logr.New(logMock) + + restConfig := &rest.Config{} + recorderMock := newMockEventRecorder(t) + ctrlManMock := newMockControllerManager(t) + ctrlManMock.EXPECT().GetEventRecorderFor("k8s-backup-operator").Return(recorderMock) + ctrlManMock.EXPECT().GetConfig().Return(restConfig) + ctrlManMock.EXPECT().GetControllerOptions().Return(config.Controller{}) + ctrlManMock.EXPECT().GetScheme().Return(createScheme(t)) + ctrlManMock.EXPECT().GetLogger().Return(logr.New(logMock)) + ctrlManMock.EXPECT().Add(mock.Anything).Return(nil) + ctrlManMock.EXPECT().GetCache().Return(nil) + ctrlManMock.EXPECT().AddHealthzCheck("healthz", mock.Anything).Return(nil) + ctrlManMock.EXPECT().AddReadyzCheck("readyz", mock.Anything).Return(nil) + ctrlManMock.EXPECT().Start(mock.Anything).Return(nil) + + ctrl.NewManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) { + return ctrlManMock, nil + } + ctrl.GetConfigOrDie = func() *rest.Config { + return restConfig + } + ctrl.SetupSignalHandler = func() context.Context { + return testCtx + } + + // when + err := startOperator() + + // then + require.NoError(t, err) + }) +} + +func createScheme(t *testing.T) *runtime.Scheme { + t.Helper() + + scheme := runtime.NewScheme() + gv, err := schema.ParseGroupVersion("k8s.cloudogu.com/v1") + assert.NoError(t, err) + + scheme.AddKnownTypes(gv, &v1.Backup{}, &v1.Restore{}) + return scheme +} diff --git a/mock_controllerManager_test.go b/mock_controllerManager_test.go new file mode 100644 index 0000000..ae04a08 --- /dev/null +++ b/mock_controllerManager_test.go @@ -0,0 +1,786 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package main + +import ( + cache "sigs.k8s.io/controller-runtime/pkg/cache" + client "sigs.k8s.io/controller-runtime/pkg/client" + + config "sigs.k8s.io/controller-runtime/pkg/config" + + context "context" + + healthz "sigs.k8s.io/controller-runtime/pkg/healthz" + + http "net/http" + + logr "github.com/go-logr/logr" + + manager "sigs.k8s.io/controller-runtime/pkg/manager" + + meta "k8s.io/apimachinery/pkg/api/meta" + + mock "github.com/stretchr/testify/mock" + + record "k8s.io/client-go/tools/record" + + rest "k8s.io/client-go/rest" + + runtime "k8s.io/apimachinery/pkg/runtime" + + webhook "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// mockControllerManager is an autogenerated mock type for the controllerManager type +type mockControllerManager struct { + mock.Mock +} + +type mockControllerManager_Expecter struct { + mock *mock.Mock +} + +func (_m *mockControllerManager) EXPECT() *mockControllerManager_Expecter { + return &mockControllerManager_Expecter{mock: &_m.Mock} +} + +// Add provides a mock function with given fields: _a0 +func (_m *mockControllerManager) Add(_a0 manager.Runnable) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(manager.Runnable) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' +type mockControllerManager_Add_Call struct { + *mock.Call +} + +// Add is a helper method to define mock.On call +// - _a0 manager.Runnable +func (_e *mockControllerManager_Expecter) Add(_a0 interface{}) *mockControllerManager_Add_Call { + return &mockControllerManager_Add_Call{Call: _e.mock.On("Add", _a0)} +} + +func (_c *mockControllerManager_Add_Call) Run(run func(_a0 manager.Runnable)) *mockControllerManager_Add_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(manager.Runnable)) + }) + return _c +} + +func (_c *mockControllerManager_Add_Call) Return(_a0 error) *mockControllerManager_Add_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Add_Call) RunAndReturn(run func(manager.Runnable) error) *mockControllerManager_Add_Call { + _c.Call.Return(run) + return _c +} + +// AddHealthzCheck provides a mock function with given fields: name, check +func (_m *mockControllerManager) AddHealthzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_AddHealthzCheck_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddHealthzCheck' +type mockControllerManager_AddHealthzCheck_Call struct { + *mock.Call +} + +// AddHealthzCheck is a helper method to define mock.On call +// - name string +// - check healthz.Checker +func (_e *mockControllerManager_Expecter) AddHealthzCheck(name interface{}, check interface{}) *mockControllerManager_AddHealthzCheck_Call { + return &mockControllerManager_AddHealthzCheck_Call{Call: _e.mock.On("AddHealthzCheck", name, check)} +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) Run(run func(name string, check healthz.Checker)) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(healthz.Checker)) + }) + return _c +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) Return(_a0 error) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_AddHealthzCheck_Call) RunAndReturn(run func(string, healthz.Checker) error) *mockControllerManager_AddHealthzCheck_Call { + _c.Call.Return(run) + return _c +} + +// AddReadyzCheck provides a mock function with given fields: name, check +func (_m *mockControllerManager) AddReadyzCheck(name string, check healthz.Checker) error { + ret := _m.Called(name, check) + + var r0 error + if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { + r0 = rf(name, check) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_AddReadyzCheck_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddReadyzCheck' +type mockControllerManager_AddReadyzCheck_Call struct { + *mock.Call +} + +// AddReadyzCheck is a helper method to define mock.On call +// - name string +// - check healthz.Checker +func (_e *mockControllerManager_Expecter) AddReadyzCheck(name interface{}, check interface{}) *mockControllerManager_AddReadyzCheck_Call { + return &mockControllerManager_AddReadyzCheck_Call{Call: _e.mock.On("AddReadyzCheck", name, check)} +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) Run(run func(name string, check healthz.Checker)) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].(healthz.Checker)) + }) + return _c +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) Return(_a0 error) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_AddReadyzCheck_Call) RunAndReturn(run func(string, healthz.Checker) error) *mockControllerManager_AddReadyzCheck_Call { + _c.Call.Return(run) + return _c +} + +// Elected provides a mock function with given fields: +func (_m *mockControllerManager) Elected() <-chan struct{} { + ret := _m.Called() + + var r0 <-chan struct{} + if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(<-chan struct{}) + } + } + + return r0 +} + +// mockControllerManager_Elected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Elected' +type mockControllerManager_Elected_Call struct { + *mock.Call +} + +// Elected is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) Elected() *mockControllerManager_Elected_Call { + return &mockControllerManager_Elected_Call{Call: _e.mock.On("Elected")} +} + +func (_c *mockControllerManager_Elected_Call) Run(run func()) *mockControllerManager_Elected_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_Elected_Call) Return(_a0 <-chan struct{}) *mockControllerManager_Elected_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Elected_Call) RunAndReturn(run func() <-chan struct{}) *mockControllerManager_Elected_Call { + _c.Call.Return(run) + return _c +} + +// GetAPIReader provides a mock function with given fields: +func (_m *mockControllerManager) GetAPIReader() client.Reader { + ret := _m.Called() + + var r0 client.Reader + if rf, ok := ret.Get(0).(func() client.Reader); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Reader) + } + } + + return r0 +} + +// mockControllerManager_GetAPIReader_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAPIReader' +type mockControllerManager_GetAPIReader_Call struct { + *mock.Call +} + +// GetAPIReader is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetAPIReader() *mockControllerManager_GetAPIReader_Call { + return &mockControllerManager_GetAPIReader_Call{Call: _e.mock.On("GetAPIReader")} +} + +func (_c *mockControllerManager_GetAPIReader_Call) Run(run func()) *mockControllerManager_GetAPIReader_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetAPIReader_Call) Return(_a0 client.Reader) *mockControllerManager_GetAPIReader_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetAPIReader_Call) RunAndReturn(run func() client.Reader) *mockControllerManager_GetAPIReader_Call { + _c.Call.Return(run) + return _c +} + +// GetCache provides a mock function with given fields: +func (_m *mockControllerManager) GetCache() cache.Cache { + ret := _m.Called() + + var r0 cache.Cache + if rf, ok := ret.Get(0).(func() cache.Cache); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cache.Cache) + } + } + + return r0 +} + +// mockControllerManager_GetCache_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCache' +type mockControllerManager_GetCache_Call struct { + *mock.Call +} + +// GetCache is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetCache() *mockControllerManager_GetCache_Call { + return &mockControllerManager_GetCache_Call{Call: _e.mock.On("GetCache")} +} + +func (_c *mockControllerManager_GetCache_Call) Run(run func()) *mockControllerManager_GetCache_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetCache_Call) Return(_a0 cache.Cache) *mockControllerManager_GetCache_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetCache_Call) RunAndReturn(run func() cache.Cache) *mockControllerManager_GetCache_Call { + _c.Call.Return(run) + return _c +} + +// GetClient provides a mock function with given fields: +func (_m *mockControllerManager) GetClient() client.Client { + ret := _m.Called() + + var r0 client.Client + if rf, ok := ret.Get(0).(func() client.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.Client) + } + } + + return r0 +} + +// mockControllerManager_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' +type mockControllerManager_GetClient_Call struct { + *mock.Call +} + +// GetClient is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetClient() *mockControllerManager_GetClient_Call { + return &mockControllerManager_GetClient_Call{Call: _e.mock.On("GetClient")} +} + +func (_c *mockControllerManager_GetClient_Call) Run(run func()) *mockControllerManager_GetClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetClient_Call) Return(_a0 client.Client) *mockControllerManager_GetClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetClient_Call) RunAndReturn(run func() client.Client) *mockControllerManager_GetClient_Call { + _c.Call.Return(run) + return _c +} + +// GetConfig provides a mock function with given fields: +func (_m *mockControllerManager) GetConfig() *rest.Config { + ret := _m.Called() + + var r0 *rest.Config + if rf, ok := ret.Get(0).(func() *rest.Config); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Config) + } + } + + return r0 +} + +// mockControllerManager_GetConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetConfig' +type mockControllerManager_GetConfig_Call struct { + *mock.Call +} + +// GetConfig is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetConfig() *mockControllerManager_GetConfig_Call { + return &mockControllerManager_GetConfig_Call{Call: _e.mock.On("GetConfig")} +} + +func (_c *mockControllerManager_GetConfig_Call) Run(run func()) *mockControllerManager_GetConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetConfig_Call) Return(_a0 *rest.Config) *mockControllerManager_GetConfig_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetConfig_Call) RunAndReturn(run func() *rest.Config) *mockControllerManager_GetConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetControllerOptions provides a mock function with given fields: +func (_m *mockControllerManager) GetControllerOptions() config.Controller { + ret := _m.Called() + + var r0 config.Controller + if rf, ok := ret.Get(0).(func() config.Controller); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(config.Controller) + } + + return r0 +} + +// mockControllerManager_GetControllerOptions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetControllerOptions' +type mockControllerManager_GetControllerOptions_Call struct { + *mock.Call +} + +// GetControllerOptions is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetControllerOptions() *mockControllerManager_GetControllerOptions_Call { + return &mockControllerManager_GetControllerOptions_Call{Call: _e.mock.On("GetControllerOptions")} +} + +func (_c *mockControllerManager_GetControllerOptions_Call) Run(run func()) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetControllerOptions_Call) Return(_a0 config.Controller) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetControllerOptions_Call) RunAndReturn(run func() config.Controller) *mockControllerManager_GetControllerOptions_Call { + _c.Call.Return(run) + return _c +} + +// GetEventRecorderFor provides a mock function with given fields: name +func (_m *mockControllerManager) GetEventRecorderFor(name string) record.EventRecorder { + ret := _m.Called(name) + + var r0 record.EventRecorder + if rf, ok := ret.Get(0).(func(string) record.EventRecorder); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(record.EventRecorder) + } + } + + return r0 +} + +// mockControllerManager_GetEventRecorderFor_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventRecorderFor' +type mockControllerManager_GetEventRecorderFor_Call struct { + *mock.Call +} + +// GetEventRecorderFor is a helper method to define mock.On call +// - name string +func (_e *mockControllerManager_Expecter) GetEventRecorderFor(name interface{}) *mockControllerManager_GetEventRecorderFor_Call { + return &mockControllerManager_GetEventRecorderFor_Call{Call: _e.mock.On("GetEventRecorderFor", name)} +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) Run(run func(name string)) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) Return(_a0 record.EventRecorder) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetEventRecorderFor_Call) RunAndReturn(run func(string) record.EventRecorder) *mockControllerManager_GetEventRecorderFor_Call { + _c.Call.Return(run) + return _c +} + +// GetFieldIndexer provides a mock function with given fields: +func (_m *mockControllerManager) GetFieldIndexer() client.FieldIndexer { + ret := _m.Called() + + var r0 client.FieldIndexer + if rf, ok := ret.Get(0).(func() client.FieldIndexer); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(client.FieldIndexer) + } + } + + return r0 +} + +// mockControllerManager_GetFieldIndexer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFieldIndexer' +type mockControllerManager_GetFieldIndexer_Call struct { + *mock.Call +} + +// GetFieldIndexer is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetFieldIndexer() *mockControllerManager_GetFieldIndexer_Call { + return &mockControllerManager_GetFieldIndexer_Call{Call: _e.mock.On("GetFieldIndexer")} +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) Run(run func()) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) Return(_a0 client.FieldIndexer) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetFieldIndexer_Call) RunAndReturn(run func() client.FieldIndexer) *mockControllerManager_GetFieldIndexer_Call { + _c.Call.Return(run) + return _c +} + +// GetHTTPClient provides a mock function with given fields: +func (_m *mockControllerManager) GetHTTPClient() *http.Client { + ret := _m.Called() + + var r0 *http.Client + if rf, ok := ret.Get(0).(func() *http.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Client) + } + } + + return r0 +} + +// mockControllerManager_GetHTTPClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHTTPClient' +type mockControllerManager_GetHTTPClient_Call struct { + *mock.Call +} + +// GetHTTPClient is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetHTTPClient() *mockControllerManager_GetHTTPClient_Call { + return &mockControllerManager_GetHTTPClient_Call{Call: _e.mock.On("GetHTTPClient")} +} + +func (_c *mockControllerManager_GetHTTPClient_Call) Run(run func()) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetHTTPClient_Call) Return(_a0 *http.Client) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetHTTPClient_Call) RunAndReturn(run func() *http.Client) *mockControllerManager_GetHTTPClient_Call { + _c.Call.Return(run) + return _c +} + +// GetLogger provides a mock function with given fields: +func (_m *mockControllerManager) GetLogger() logr.Logger { + ret := _m.Called() + + var r0 logr.Logger + if rf, ok := ret.Get(0).(func() logr.Logger); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(logr.Logger) + } + + return r0 +} + +// mockControllerManager_GetLogger_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLogger' +type mockControllerManager_GetLogger_Call struct { + *mock.Call +} + +// GetLogger is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetLogger() *mockControllerManager_GetLogger_Call { + return &mockControllerManager_GetLogger_Call{Call: _e.mock.On("GetLogger")} +} + +func (_c *mockControllerManager_GetLogger_Call) Run(run func()) *mockControllerManager_GetLogger_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetLogger_Call) Return(_a0 logr.Logger) *mockControllerManager_GetLogger_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetLogger_Call) RunAndReturn(run func() logr.Logger) *mockControllerManager_GetLogger_Call { + _c.Call.Return(run) + return _c +} + +// GetRESTMapper provides a mock function with given fields: +func (_m *mockControllerManager) GetRESTMapper() meta.RESTMapper { + ret := _m.Called() + + var r0 meta.RESTMapper + if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(meta.RESTMapper) + } + } + + return r0 +} + +// mockControllerManager_GetRESTMapper_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRESTMapper' +type mockControllerManager_GetRESTMapper_Call struct { + *mock.Call +} + +// GetRESTMapper is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetRESTMapper() *mockControllerManager_GetRESTMapper_Call { + return &mockControllerManager_GetRESTMapper_Call{Call: _e.mock.On("GetRESTMapper")} +} + +func (_c *mockControllerManager_GetRESTMapper_Call) Run(run func()) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetRESTMapper_Call) Return(_a0 meta.RESTMapper) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetRESTMapper_Call) RunAndReturn(run func() meta.RESTMapper) *mockControllerManager_GetRESTMapper_Call { + _c.Call.Return(run) + return _c +} + +// GetScheme provides a mock function with given fields: +func (_m *mockControllerManager) GetScheme() *runtime.Scheme { + ret := _m.Called() + + var r0 *runtime.Scheme + if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.Scheme) + } + } + + return r0 +} + +// mockControllerManager_GetScheme_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetScheme' +type mockControllerManager_GetScheme_Call struct { + *mock.Call +} + +// GetScheme is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetScheme() *mockControllerManager_GetScheme_Call { + return &mockControllerManager_GetScheme_Call{Call: _e.mock.On("GetScheme")} +} + +func (_c *mockControllerManager_GetScheme_Call) Run(run func()) *mockControllerManager_GetScheme_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetScheme_Call) Return(_a0 *runtime.Scheme) *mockControllerManager_GetScheme_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetScheme_Call) RunAndReturn(run func() *runtime.Scheme) *mockControllerManager_GetScheme_Call { + _c.Call.Return(run) + return _c +} + +// GetWebhookServer provides a mock function with given fields: +func (_m *mockControllerManager) GetWebhookServer() webhook.Server { + ret := _m.Called() + + var r0 webhook.Server + if rf, ok := ret.Get(0).(func() webhook.Server); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(webhook.Server) + } + } + + return r0 +} + +// mockControllerManager_GetWebhookServer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWebhookServer' +type mockControllerManager_GetWebhookServer_Call struct { + *mock.Call +} + +// GetWebhookServer is a helper method to define mock.On call +func (_e *mockControllerManager_Expecter) GetWebhookServer() *mockControllerManager_GetWebhookServer_Call { + return &mockControllerManager_GetWebhookServer_Call{Call: _e.mock.On("GetWebhookServer")} +} + +func (_c *mockControllerManager_GetWebhookServer_Call) Run(run func()) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockControllerManager_GetWebhookServer_Call) Return(_a0 webhook.Server) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_GetWebhookServer_Call) RunAndReturn(run func() webhook.Server) *mockControllerManager_GetWebhookServer_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: ctx +func (_m *mockControllerManager) Start(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockControllerManager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type mockControllerManager_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - ctx context.Context +func (_e *mockControllerManager_Expecter) Start(ctx interface{}) *mockControllerManager_Start_Call { + return &mockControllerManager_Start_Call{Call: _e.mock.On("Start", ctx)} +} + +func (_c *mockControllerManager_Start_Call) Run(run func(ctx context.Context)) *mockControllerManager_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockControllerManager_Start_Call) Return(_a0 error) *mockControllerManager_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockControllerManager_Start_Call) RunAndReturn(run func(context.Context) error) *mockControllerManager_Start_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockControllerManager interface { + mock.TestingT + Cleanup(func()) +} + +// newMockControllerManager creates a new instance of mockControllerManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockControllerManager(t mockConstructorTestingTnewMockControllerManager) *mockControllerManager { + mock := &mockControllerManager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mock_eventRecorder_test.go b/mock_eventRecorder_test.go new file mode 100644 index 0000000..326c8a9 --- /dev/null +++ b/mock_eventRecorder_test.go @@ -0,0 +1,167 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package main + +import ( + mock "github.com/stretchr/testify/mock" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// mockEventRecorder is an autogenerated mock type for the eventRecorder type +type mockEventRecorder struct { + mock.Mock +} + +type mockEventRecorder_Expecter struct { + mock *mock.Mock +} + +func (_m *mockEventRecorder) EXPECT() *mockEventRecorder_Expecter { + return &mockEventRecorder_Expecter{mock: &_m.Mock} +} + +// AnnotatedEventf provides a mock function with given fields: object, annotations, eventtype, reason, messageFmt, args +func (_m *mockEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, annotations, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// mockEventRecorder_AnnotatedEventf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AnnotatedEventf' +type mockEventRecorder_AnnotatedEventf_Call struct { + *mock.Call +} + +// AnnotatedEventf is a helper method to define mock.On call +// - object runtime.Object +// - annotations map[string]string +// - eventtype string +// - reason string +// - messageFmt string +// - args ...interface{} +func (_e *mockEventRecorder_Expecter) AnnotatedEventf(object interface{}, annotations interface{}, eventtype interface{}, reason interface{}, messageFmt interface{}, args ...interface{}) *mockEventRecorder_AnnotatedEventf_Call { + return &mockEventRecorder_AnnotatedEventf_Call{Call: _e.mock.On("AnnotatedEventf", + append([]interface{}{object, annotations, eventtype, reason, messageFmt}, args...)...)} +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) Run(run func(object runtime.Object, annotations map[string]string, eventtype string, reason string, messageFmt string, args ...interface{})) *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-5) + for i, a := range args[5:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(runtime.Object), args[1].(map[string]string), args[2].(string), args[3].(string), args[4].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) Return() *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_AnnotatedEventf_Call) RunAndReturn(run func(runtime.Object, map[string]string, string, string, string, ...interface{})) *mockEventRecorder_AnnotatedEventf_Call { + _c.Call.Return(run) + return _c +} + +// Event provides a mock function with given fields: object, eventtype, reason, message +func (_m *mockEventRecorder) Event(object runtime.Object, eventtype string, reason string, message string) { + _m.Called(object, eventtype, reason, message) +} + +// mockEventRecorder_Event_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Event' +type mockEventRecorder_Event_Call struct { + *mock.Call +} + +// Event is a helper method to define mock.On call +// - object runtime.Object +// - eventtype string +// - reason string +// - message string +func (_e *mockEventRecorder_Expecter) Event(object interface{}, eventtype interface{}, reason interface{}, message interface{}) *mockEventRecorder_Event_Call { + return &mockEventRecorder_Event_Call{Call: _e.mock.On("Event", object, eventtype, reason, message)} +} + +func (_c *mockEventRecorder_Event_Call) Run(run func(object runtime.Object, eventtype string, reason string, message string)) *mockEventRecorder_Event_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(runtime.Object), args[1].(string), args[2].(string), args[3].(string)) + }) + return _c +} + +func (_c *mockEventRecorder_Event_Call) Return() *mockEventRecorder_Event_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_Event_Call) RunAndReturn(run func(runtime.Object, string, string, string)) *mockEventRecorder_Event_Call { + _c.Call.Return(run) + return _c +} + +// Eventf provides a mock function with given fields: object, eventtype, reason, messageFmt, args +func (_m *mockEventRecorder) Eventf(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, object, eventtype, reason, messageFmt) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// mockEventRecorder_Eventf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Eventf' +type mockEventRecorder_Eventf_Call struct { + *mock.Call +} + +// Eventf is a helper method to define mock.On call +// - object runtime.Object +// - eventtype string +// - reason string +// - messageFmt string +// - args ...interface{} +func (_e *mockEventRecorder_Expecter) Eventf(object interface{}, eventtype interface{}, reason interface{}, messageFmt interface{}, args ...interface{}) *mockEventRecorder_Eventf_Call { + return &mockEventRecorder_Eventf_Call{Call: _e.mock.On("Eventf", + append([]interface{}{object, eventtype, reason, messageFmt}, args...)...)} +} + +func (_c *mockEventRecorder_Eventf_Call) Run(run func(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{})) *mockEventRecorder_Eventf_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-4) + for i, a := range args[4:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(runtime.Object), args[1].(string), args[2].(string), args[3].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockEventRecorder_Eventf_Call) Return() *mockEventRecorder_Eventf_Call { + _c.Call.Return() + return _c +} + +func (_c *mockEventRecorder_Eventf_Call) RunAndReturn(run func(runtime.Object, string, string, string, ...interface{})) *mockEventRecorder_Eventf_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockEventRecorder interface { + mock.TestingT + Cleanup(func()) +} + +// newMockEventRecorder creates a new instance of mockEventRecorder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockEventRecorder(t mockConstructorTestingTnewMockEventRecorder) *mockEventRecorder { + mock := &mockEventRecorder{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mock_logSink_test.go b/mock_logSink_test.go new file mode 100644 index 0000000..46f8142 --- /dev/null +++ b/mock_logSink_test.go @@ -0,0 +1,298 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package main + +import ( + logr "github.com/go-logr/logr" + mock "github.com/stretchr/testify/mock" +) + +// mockLogSink is an autogenerated mock type for the logSink type +type mockLogSink struct { + mock.Mock +} + +type mockLogSink_Expecter struct { + mock *mock.Mock +} + +func (_m *mockLogSink) EXPECT() *mockLogSink_Expecter { + return &mockLogSink_Expecter{mock: &_m.Mock} +} + +// Enabled provides a mock function with given fields: level +func (_m *mockLogSink) Enabled(level int) bool { + ret := _m.Called(level) + + var r0 bool + if rf, ok := ret.Get(0).(func(int) bool); ok { + r0 = rf(level) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// mockLogSink_Enabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Enabled' +type mockLogSink_Enabled_Call struct { + *mock.Call +} + +// Enabled is a helper method to define mock.On call +// - level int +func (_e *mockLogSink_Expecter) Enabled(level interface{}) *mockLogSink_Enabled_Call { + return &mockLogSink_Enabled_Call{Call: _e.mock.On("Enabled", level)} +} + +func (_c *mockLogSink_Enabled_Call) Run(run func(level int)) *mockLogSink_Enabled_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *mockLogSink_Enabled_Call) Return(_a0 bool) *mockLogSink_Enabled_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_Enabled_Call) RunAndReturn(run func(int) bool) *mockLogSink_Enabled_Call { + _c.Call.Return(run) + return _c +} + +// Error provides a mock function with given fields: err, msg, keysAndValues +func (_m *mockLogSink) Error(err error, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, err, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// mockLogSink_Error_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Error' +type mockLogSink_Error_Call struct { + *mock.Call +} + +// Error is a helper method to define mock.On call +// - err error +// - msg string +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) Error(err interface{}, msg interface{}, keysAndValues ...interface{}) *mockLogSink_Error_Call { + return &mockLogSink_Error_Call{Call: _e.mock.On("Error", + append([]interface{}{err, msg}, keysAndValues...)...)} +} + +func (_c *mockLogSink_Error_Call) Run(run func(err error, msg string, keysAndValues ...interface{})) *mockLogSink_Error_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(error), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_Error_Call) Return() *mockLogSink_Error_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Error_Call) RunAndReturn(run func(error, string, ...interface{})) *mockLogSink_Error_Call { + _c.Call.Return(run) + return _c +} + +// Info provides a mock function with given fields: level, msg, keysAndValues +func (_m *mockLogSink) Info(level int, msg string, keysAndValues ...interface{}) { + var _ca []interface{} + _ca = append(_ca, level, msg) + _ca = append(_ca, keysAndValues...) + _m.Called(_ca...) +} + +// mockLogSink_Info_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Info' +type mockLogSink_Info_Call struct { + *mock.Call +} + +// Info is a helper method to define mock.On call +// - level int +// - msg string +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) Info(level interface{}, msg interface{}, keysAndValues ...interface{}) *mockLogSink_Info_Call { + return &mockLogSink_Info_Call{Call: _e.mock.On("Info", + append([]interface{}{level, msg}, keysAndValues...)...)} +} + +func (_c *mockLogSink_Info_Call) Run(run func(level int, msg string, keysAndValues ...interface{})) *mockLogSink_Info_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(int), args[1].(string), variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_Info_Call) Return() *mockLogSink_Info_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Info_Call) RunAndReturn(run func(int, string, ...interface{})) *mockLogSink_Info_Call { + _c.Call.Return(run) + return _c +} + +// Init provides a mock function with given fields: info +func (_m *mockLogSink) Init(info logr.RuntimeInfo) { + _m.Called(info) +} + +// mockLogSink_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init' +type mockLogSink_Init_Call struct { + *mock.Call +} + +// Init is a helper method to define mock.On call +// - info logr.RuntimeInfo +func (_e *mockLogSink_Expecter) Init(info interface{}) *mockLogSink_Init_Call { + return &mockLogSink_Init_Call{Call: _e.mock.On("Init", info)} +} + +func (_c *mockLogSink_Init_Call) Run(run func(info logr.RuntimeInfo)) *mockLogSink_Init_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(logr.RuntimeInfo)) + }) + return _c +} + +func (_c *mockLogSink_Init_Call) Return() *mockLogSink_Init_Call { + _c.Call.Return() + return _c +} + +func (_c *mockLogSink_Init_Call) RunAndReturn(run func(logr.RuntimeInfo)) *mockLogSink_Init_Call { + _c.Call.Return(run) + return _c +} + +// WithName provides a mock function with given fields: name +func (_m *mockLogSink) WithName(name string) logr.LogSink { + ret := _m.Called(name) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(string) logr.LogSink); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +// mockLogSink_WithName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithName' +type mockLogSink_WithName_Call struct { + *mock.Call +} + +// WithName is a helper method to define mock.On call +// - name string +func (_e *mockLogSink_Expecter) WithName(name interface{}) *mockLogSink_WithName_Call { + return &mockLogSink_WithName_Call{Call: _e.mock.On("WithName", name)} +} + +func (_c *mockLogSink_WithName_Call) Run(run func(name string)) *mockLogSink_WithName_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockLogSink_WithName_Call) Return(_a0 logr.LogSink) *mockLogSink_WithName_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_WithName_Call) RunAndReturn(run func(string) logr.LogSink) *mockLogSink_WithName_Call { + _c.Call.Return(run) + return _c +} + +// WithValues provides a mock function with given fields: keysAndValues +func (_m *mockLogSink) WithValues(keysAndValues ...interface{}) logr.LogSink { + var _ca []interface{} + _ca = append(_ca, keysAndValues...) + ret := _m.Called(_ca...) + + var r0 logr.LogSink + if rf, ok := ret.Get(0).(func(...interface{}) logr.LogSink); ok { + r0 = rf(keysAndValues...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(logr.LogSink) + } + } + + return r0 +} + +// mockLogSink_WithValues_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithValues' +type mockLogSink_WithValues_Call struct { + *mock.Call +} + +// WithValues is a helper method to define mock.On call +// - keysAndValues ...interface{} +func (_e *mockLogSink_Expecter) WithValues(keysAndValues ...interface{}) *mockLogSink_WithValues_Call { + return &mockLogSink_WithValues_Call{Call: _e.mock.On("WithValues", + append([]interface{}{}, keysAndValues...)...)} +} + +func (_c *mockLogSink_WithValues_Call) Run(run func(keysAndValues ...interface{})) *mockLogSink_WithValues_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *mockLogSink_WithValues_Call) Return(_a0 logr.LogSink) *mockLogSink_WithValues_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockLogSink_WithValues_Call) RunAndReturn(run func(...interface{}) logr.LogSink) *mockLogSink_WithValues_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockLogSink interface { + mock.TestingT + Cleanup(func()) +} + +// newMockLogSink creates a new instance of mockLogSink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockLogSink(t mockConstructorTestingTnewMockLogSink) *mockLogSink { + mock := &mockLogSink{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From 5b66bc56e5f9d409bb9566afe747180e87a7149f Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 15:47:59 +0200 Subject: [PATCH 28/37] #1 Extract interfaces for better mock generation --- main.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 56f87a7..fcc1664 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "k8s.io/client-go/tools/record" "os" "k8s.io/apimachinery/pkg/runtime" @@ -37,6 +38,14 @@ var ( Version = "0.0.0" ) +type eventRecorder interface { + record.EventRecorder +} + +type controllerManager interface { + manager.Manager +} + func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(k8sv1.AddToScheme(scheme)) @@ -72,7 +81,7 @@ func startOperator() error { return startK8sManager(k8sManager) } -func configureManager(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { +func configureManager(k8sManager controllerManager, operatorConfig *config.OperatorConfig) error { err := configureReconcilers(k8sManager, operatorConfig) if err != nil { return fmt.Errorf("unable to configure reconciler: %w", err) @@ -125,8 +134,8 @@ var parseFlags = func(options ctrl.Options) (ctrl.Options, zap.Options) { return options, opts } -func configureReconcilers(k8sManager manager.Manager, operatorConfig *config.OperatorConfig) error { - eventRecorder := k8sManager.GetEventRecorderFor("k8s-backup-operator") +func configureReconcilers(k8sManager controllerManager, operatorConfig *config.OperatorConfig) error { + var eventRecorder eventRecorder = k8sManager.GetEventRecorderFor("k8s-backup-operator") k8sClientSet, err := kubernetes.NewForConfig(k8sManager.GetConfig()) if err != nil { @@ -149,7 +158,7 @@ func configureReconcilers(k8sManager manager.Manager, operatorConfig *config.Ope return nil } -func addChecks(k8sManager manager.Manager) error { +func addChecks(k8sManager controllerManager) error { if err := k8sManager.AddHealthzCheck("healthz", healthz.Ping); err != nil { return fmt.Errorf("unable to set up health check: %w", err) } @@ -160,7 +169,7 @@ func addChecks(k8sManager manager.Manager) error { return nil } -func startK8sManager(k8sManager manager.Manager) error { +func startK8sManager(k8sManager controllerManager) error { setupLog.Info("starting manager") if err := k8sManager.Start(ctrl.SetupSignalHandler()); err != nil { return fmt.Errorf("problem running manager: %w", err) From 8cabc7600a636994e992b17a089da23f5749e480 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 16:25:42 +0200 Subject: [PATCH 29/37] #1 Test ecosystem client set --- pkg/api/ecosystem/ecosystemClientSet.go | 6 +- pkg/api/ecosystem/ecosystemClientSet_test.go | 104 +++++ .../ecosystem/mock_V1Alpha1Interface_test.go | 121 ++++++ pkg/api/ecosystem/mock_restInterface_test.go | 386 ++++++++++++++++++ 4 files changed, 616 insertions(+), 1 deletion(-) create mode 100644 pkg/api/ecosystem/ecosystemClientSet_test.go create mode 100644 pkg/api/ecosystem/mock_V1Alpha1Interface_test.go create mode 100644 pkg/api/ecosystem/mock_restInterface_test.go diff --git a/pkg/api/ecosystem/ecosystemClientSet.go b/pkg/api/ecosystem/ecosystemClientSet.go index 74ef854..a37c166 100644 --- a/pkg/api/ecosystem/ecosystemClientSet.go +++ b/pkg/api/ecosystem/ecosystemClientSet.go @@ -82,9 +82,13 @@ func NewForConfig(c *rest.Config) (*V1Alpha1Client, error) { return &V1Alpha1Client{restClient: client}, nil } +type restInterface interface { + rest.Interface +} + // V1Alpha1Client is a getter for the custom resources of this operator. type V1Alpha1Client struct { - restClient rest.Interface + restClient restInterface } // Backups returns a client for backups in the given namespace. diff --git a/pkg/api/ecosystem/ecosystemClientSet_test.go b/pkg/api/ecosystem/ecosystemClientSet_test.go new file mode 100644 index 0000000..1f8058b --- /dev/null +++ b/pkg/api/ecosystem/ecosystemClientSet_test.go @@ -0,0 +1,104 @@ +package ecosystem + +import ( + "k8s.io/apimachinery/pkg/runtime" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "k8s.io/client-go/rest" + + v1 "github.com/cloudogu/k8s-backup-operator/pkg/api/v1" +) + +func TestNewClientSet(t *testing.T) { + t.Run("should fail to add to scheme", func(t *testing.T) { + // given + oldAddToSchemeFunc := v1.AddToScheme + defer func() { v1.AddToScheme = oldAddToSchemeFunc }() + v1.AddToScheme = func(_ *runtime.Scheme) error { + return assert.AnError + } + + restCfg := &rest.Config{} + + // when + actual, err := NewClientSet(restCfg, nil) + + // then + require.Error(t, err) + assert.ErrorIs(t, err, assert.AnError) + assert.Nil(t, actual) + }) + t.Run("should fail to create rest client", func(t *testing.T) { + // given + restCfg := &rest.Config{} + restCfg.Host = "\\" + + // when + actual, err := NewClientSet(restCfg, nil) + + // then + require.Error(t, err) + assert.ErrorContains(t, err, "parse \"http://\\\\\": invalid character \"\\\\\" in host name") + assert.Nil(t, actual) + }) + t.Run("should succeed", func(t *testing.T) { + // given + restCfg := &rest.Config{} + + // when + actual, err := NewClientSet(restCfg, nil) + + // then + require.NoError(t, err) + assert.NotNil(t, actual) + assert.NotNil(t, actual.ecosystemV1Alpha1) + }) +} + +func TestClientSet_EcosystemV1Alpha1(t *testing.T) { + t.Run("should return getter", func(t *testing.T) { + // given + alpha1InterfaceMock := NewMockV1Alpha1Interface(t) + sut := &ClientSet{ecosystemV1Alpha1: alpha1InterfaceMock} + + // when + actual := sut.EcosystemV1Alpha1() + + // then + assert.Same(t, alpha1InterfaceMock, actual) + }) +} + +func TestV1Alpha1Client_Backups(t *testing.T) { + t.Run("should return backup client", func(t *testing.T) { + // given + restClientMock := newMockRestInterface(t) + sut := &V1Alpha1Client{restClient: restClientMock} + + // when + actual := sut.Backups("ecosystem") + + // then + require.NotNil(t, actual) + assert.IsType(t, &backupClient{}, actual) + assert.Same(t, restClientMock, actual.(*backupClient).client) + assert.Equal(t, "ecosystem", actual.(*backupClient).ns) + }) + t.Run("should return restore client", func(t *testing.T) { + // given + restClientMock := newMockRestInterface(t) + sut := &V1Alpha1Client{restClient: restClientMock} + + // when + actual := sut.Restores("ecosystem") + + // then + require.NotNil(t, actual) + assert.IsType(t, &restoreClient{}, actual) + assert.Same(t, restClientMock, actual.(*restoreClient).client) + assert.Equal(t, "ecosystem", actual.(*restoreClient).ns) + }) +} diff --git a/pkg/api/ecosystem/mock_V1Alpha1Interface_test.go b/pkg/api/ecosystem/mock_V1Alpha1Interface_test.go new file mode 100644 index 0000000..a6a0d67 --- /dev/null +++ b/pkg/api/ecosystem/mock_V1Alpha1Interface_test.go @@ -0,0 +1,121 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package ecosystem + +import mock "github.com/stretchr/testify/mock" + +// MockV1Alpha1Interface is an autogenerated mock type for the V1Alpha1Interface type +type MockV1Alpha1Interface struct { + mock.Mock +} + +type MockV1Alpha1Interface_Expecter struct { + mock *mock.Mock +} + +func (_m *MockV1Alpha1Interface) EXPECT() *MockV1Alpha1Interface_Expecter { + return &MockV1Alpha1Interface_Expecter{mock: &_m.Mock} +} + +// Backups provides a mock function with given fields: namespace +func (_m *MockV1Alpha1Interface) Backups(namespace string) BackupInterface { + ret := _m.Called(namespace) + + var r0 BackupInterface + if rf, ok := ret.Get(0).(func(string) BackupInterface); ok { + r0 = rf(namespace) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(BackupInterface) + } + } + + return r0 +} + +// MockV1Alpha1Interface_Backups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Backups' +type MockV1Alpha1Interface_Backups_Call struct { + *mock.Call +} + +// Backups is a helper method to define mock.On call +// - namespace string +func (_e *MockV1Alpha1Interface_Expecter) Backups(namespace interface{}) *MockV1Alpha1Interface_Backups_Call { + return &MockV1Alpha1Interface_Backups_Call{Call: _e.mock.On("Backups", namespace)} +} + +func (_c *MockV1Alpha1Interface_Backups_Call) Run(run func(namespace string)) *MockV1Alpha1Interface_Backups_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockV1Alpha1Interface_Backups_Call) Return(_a0 BackupInterface) *MockV1Alpha1Interface_Backups_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockV1Alpha1Interface_Backups_Call) RunAndReturn(run func(string) BackupInterface) *MockV1Alpha1Interface_Backups_Call { + _c.Call.Return(run) + return _c +} + +// Restores provides a mock function with given fields: namespace +func (_m *MockV1Alpha1Interface) Restores(namespace string) RestoreInterface { + ret := _m.Called(namespace) + + var r0 RestoreInterface + if rf, ok := ret.Get(0).(func(string) RestoreInterface); ok { + r0 = rf(namespace) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(RestoreInterface) + } + } + + return r0 +} + +// MockV1Alpha1Interface_Restores_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Restores' +type MockV1Alpha1Interface_Restores_Call struct { + *mock.Call +} + +// Restores is a helper method to define mock.On call +// - namespace string +func (_e *MockV1Alpha1Interface_Expecter) Restores(namespace interface{}) *MockV1Alpha1Interface_Restores_Call { + return &MockV1Alpha1Interface_Restores_Call{Call: _e.mock.On("Restores", namespace)} +} + +func (_c *MockV1Alpha1Interface_Restores_Call) Run(run func(namespace string)) *MockV1Alpha1Interface_Restores_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockV1Alpha1Interface_Restores_Call) Return(_a0 RestoreInterface) *MockV1Alpha1Interface_Restores_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockV1Alpha1Interface_Restores_Call) RunAndReturn(run func(string) RestoreInterface) *MockV1Alpha1Interface_Restores_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTNewMockV1Alpha1Interface interface { + mock.TestingT + Cleanup(func()) +} + +// NewMockV1Alpha1Interface creates a new instance of MockV1Alpha1Interface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockV1Alpha1Interface(t mockConstructorTestingTNewMockV1Alpha1Interface) *MockV1Alpha1Interface { + mock := &MockV1Alpha1Interface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/api/ecosystem/mock_restInterface_test.go b/pkg/api/ecosystem/mock_restInterface_test.go new file mode 100644 index 0000000..2ac7aec --- /dev/null +++ b/pkg/api/ecosystem/mock_restInterface_test.go @@ -0,0 +1,386 @@ +// Code generated by mockery v2.20.0. DO NOT EDIT. + +package ecosystem + +import ( + mock "github.com/stretchr/testify/mock" + flowcontrol "k8s.io/client-go/util/flowcontrol" + + rest "k8s.io/client-go/rest" + + schema "k8s.io/apimachinery/pkg/runtime/schema" + + types "k8s.io/apimachinery/pkg/types" +) + +// mockRestInterface is an autogenerated mock type for the restInterface type +type mockRestInterface struct { + mock.Mock +} + +type mockRestInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *mockRestInterface) EXPECT() *mockRestInterface_Expecter { + return &mockRestInterface_Expecter{mock: &_m.Mock} +} + +// APIVersion provides a mock function with given fields: +func (_m *mockRestInterface) APIVersion() schema.GroupVersion { + ret := _m.Called() + + var r0 schema.GroupVersion + if rf, ok := ret.Get(0).(func() schema.GroupVersion); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(schema.GroupVersion) + } + + return r0 +} + +// mockRestInterface_APIVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'APIVersion' +type mockRestInterface_APIVersion_Call struct { + *mock.Call +} + +// APIVersion is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) APIVersion() *mockRestInterface_APIVersion_Call { + return &mockRestInterface_APIVersion_Call{Call: _e.mock.On("APIVersion")} +} + +func (_c *mockRestInterface_APIVersion_Call) Run(run func()) *mockRestInterface_APIVersion_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_APIVersion_Call) Return(_a0 schema.GroupVersion) *mockRestInterface_APIVersion_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_APIVersion_Call) RunAndReturn(run func() schema.GroupVersion) *mockRestInterface_APIVersion_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: +func (_m *mockRestInterface) Delete() *rest.Request { + ret := _m.Called() + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func() *rest.Request); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type mockRestInterface_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) Delete() *mockRestInterface_Delete_Call { + return &mockRestInterface_Delete_Call{Call: _e.mock.On("Delete")} +} + +func (_c *mockRestInterface_Delete_Call) Run(run func()) *mockRestInterface_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_Delete_Call) Return(_a0 *rest.Request) *mockRestInterface_Delete_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Delete_Call) RunAndReturn(run func() *rest.Request) *mockRestInterface_Delete_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: +func (_m *mockRestInterface) Get() *rest.Request { + ret := _m.Called() + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func() *rest.Request); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type mockRestInterface_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) Get() *mockRestInterface_Get_Call { + return &mockRestInterface_Get_Call{Call: _e.mock.On("Get")} +} + +func (_c *mockRestInterface_Get_Call) Run(run func()) *mockRestInterface_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_Get_Call) Return(_a0 *rest.Request) *mockRestInterface_Get_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Get_Call) RunAndReturn(run func() *rest.Request) *mockRestInterface_Get_Call { + _c.Call.Return(run) + return _c +} + +// GetRateLimiter provides a mock function with given fields: +func (_m *mockRestInterface) GetRateLimiter() flowcontrol.RateLimiter { + ret := _m.Called() + + var r0 flowcontrol.RateLimiter + if rf, ok := ret.Get(0).(func() flowcontrol.RateLimiter); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(flowcontrol.RateLimiter) + } + } + + return r0 +} + +// mockRestInterface_GetRateLimiter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRateLimiter' +type mockRestInterface_GetRateLimiter_Call struct { + *mock.Call +} + +// GetRateLimiter is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) GetRateLimiter() *mockRestInterface_GetRateLimiter_Call { + return &mockRestInterface_GetRateLimiter_Call{Call: _e.mock.On("GetRateLimiter")} +} + +func (_c *mockRestInterface_GetRateLimiter_Call) Run(run func()) *mockRestInterface_GetRateLimiter_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_GetRateLimiter_Call) Return(_a0 flowcontrol.RateLimiter) *mockRestInterface_GetRateLimiter_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_GetRateLimiter_Call) RunAndReturn(run func() flowcontrol.RateLimiter) *mockRestInterface_GetRateLimiter_Call { + _c.Call.Return(run) + return _c +} + +// Patch provides a mock function with given fields: pt +func (_m *mockRestInterface) Patch(pt types.PatchType) *rest.Request { + ret := _m.Called(pt) + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func(types.PatchType) *rest.Request); ok { + r0 = rf(pt) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Patch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Patch' +type mockRestInterface_Patch_Call struct { + *mock.Call +} + +// Patch is a helper method to define mock.On call +// - pt types.PatchType +func (_e *mockRestInterface_Expecter) Patch(pt interface{}) *mockRestInterface_Patch_Call { + return &mockRestInterface_Patch_Call{Call: _e.mock.On("Patch", pt)} +} + +func (_c *mockRestInterface_Patch_Call) Run(run func(pt types.PatchType)) *mockRestInterface_Patch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.PatchType)) + }) + return _c +} + +func (_c *mockRestInterface_Patch_Call) Return(_a0 *rest.Request) *mockRestInterface_Patch_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Patch_Call) RunAndReturn(run func(types.PatchType) *rest.Request) *mockRestInterface_Patch_Call { + _c.Call.Return(run) + return _c +} + +// Post provides a mock function with given fields: +func (_m *mockRestInterface) Post() *rest.Request { + ret := _m.Called() + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func() *rest.Request); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Post_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Post' +type mockRestInterface_Post_Call struct { + *mock.Call +} + +// Post is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) Post() *mockRestInterface_Post_Call { + return &mockRestInterface_Post_Call{Call: _e.mock.On("Post")} +} + +func (_c *mockRestInterface_Post_Call) Run(run func()) *mockRestInterface_Post_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_Post_Call) Return(_a0 *rest.Request) *mockRestInterface_Post_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Post_Call) RunAndReturn(run func() *rest.Request) *mockRestInterface_Post_Call { + _c.Call.Return(run) + return _c +} + +// Put provides a mock function with given fields: +func (_m *mockRestInterface) Put() *rest.Request { + ret := _m.Called() + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func() *rest.Request); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Put_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Put' +type mockRestInterface_Put_Call struct { + *mock.Call +} + +// Put is a helper method to define mock.On call +func (_e *mockRestInterface_Expecter) Put() *mockRestInterface_Put_Call { + return &mockRestInterface_Put_Call{Call: _e.mock.On("Put")} +} + +func (_c *mockRestInterface_Put_Call) Run(run func()) *mockRestInterface_Put_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *mockRestInterface_Put_Call) Return(_a0 *rest.Request) *mockRestInterface_Put_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Put_Call) RunAndReturn(run func() *rest.Request) *mockRestInterface_Put_Call { + _c.Call.Return(run) + return _c +} + +// Verb provides a mock function with given fields: verb +func (_m *mockRestInterface) Verb(verb string) *rest.Request { + ret := _m.Called(verb) + + var r0 *rest.Request + if rf, ok := ret.Get(0).(func(string) *rest.Request); ok { + r0 = rf(verb) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rest.Request) + } + } + + return r0 +} + +// mockRestInterface_Verb_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Verb' +type mockRestInterface_Verb_Call struct { + *mock.Call +} + +// Verb is a helper method to define mock.On call +// - verb string +func (_e *mockRestInterface_Expecter) Verb(verb interface{}) *mockRestInterface_Verb_Call { + return &mockRestInterface_Verb_Call{Call: _e.mock.On("Verb", verb)} +} + +func (_c *mockRestInterface_Verb_Call) Run(run func(verb string)) *mockRestInterface_Verb_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockRestInterface_Verb_Call) Return(_a0 *rest.Request) *mockRestInterface_Verb_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockRestInterface_Verb_Call) RunAndReturn(run func(string) *rest.Request) *mockRestInterface_Verb_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTnewMockRestInterface interface { + mock.TestingT + Cleanup(func()) +} + +// newMockRestInterface creates a new instance of mockRestInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newMockRestInterface(t mockConstructorTestingTnewMockRestInterface) *mockRestInterface { + mock := &mockRestInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From 2360770afb2898a1f16f14f57c83369a1d2bdeda Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 1 Sep 2023 16:51:40 +0200 Subject: [PATCH 30/37] #1 Test flag parsing Document why parse flags is a closure and can only be tested once. --- main.go | 20 +++++++++++--------- main_internal_test.go | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index fcc1664..4536cf3 100644 --- a/main.go +++ b/main.go @@ -3,13 +3,13 @@ package main import ( "flag" "fmt" - "k8s.io/client-go/tools/record" "os" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/record" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -104,7 +104,7 @@ func getK8sManagerOptions(operatorConfig *config.OperatorConfig) ctrl.Options { WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), LeaderElectionID: "e3f6c1a7.cloudogu.com", } - zapOpts := zap.Options{} + var zapOpts zap.Options controllerOpts, zapOpts = parseFlags(controllerOpts) ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zapOpts))) @@ -112,7 +112,9 @@ func getK8sManagerOptions(operatorConfig *config.OperatorConfig) ctrl.Options { return controllerOpts } -var parseFlags = func(options ctrl.Options) (ctrl.Options, zap.Options) { +// parseFlags is a closure because it panics when its called twice in tests. +// Therefore, we must overwrite it for all but one single test. +var parseFlags = func(ctrlOpts ctrl.Options) (ctrl.Options, zap.Options) { var metricsAddr string var enableLeaderElection bool var probeAddr string @@ -121,17 +123,17 @@ var parseFlags = func(options ctrl.Options) (ctrl.Options, zap.Options) { flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") - opts := zap.Options{ + zapOpts := zap.Options{ Development: config.IsStageDevelopment(), } - opts.BindFlags(flag.CommandLine) + zapOpts.BindFlags(flag.CommandLine) flag.Parse() - options.Metrics = server.Options{BindAddress: metricsAddr} - options.HealthProbeBindAddress = probeAddr - options.LeaderElection = enableLeaderElection + ctrlOpts.Metrics = server.Options{BindAddress: metricsAddr} + ctrlOpts.HealthProbeBindAddress = probeAddr + ctrlOpts.LeaderElection = enableLeaderElection - return options, opts + return ctrlOpts, zapOpts } func configureReconcilers(k8sManager controllerManager, operatorConfig *config.OperatorConfig) error { diff --git a/main_internal_test.go b/main_internal_test.go index 9c58c1f..24831f6 100644 --- a/main_internal_test.go +++ b/main_internal_test.go @@ -2,17 +2,19 @@ package main import ( "context" - "github.com/go-logr/logr" - "sigs.k8s.io/controller-runtime/pkg/log/zap" "testing" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/config" + "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "github.com/go-logr/logr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -22,6 +24,36 @@ import ( var testCtx = context.Background() +// WARNING: We can test parseFlags only one single time. +// If it is called more than once, it will panic. +// For all other tests it has to be overwritten. +func Test_parseFlags(t *testing.T) { + // given + ctrlOpts := ctrl.Options{ + Scheme: scheme, + Cache: cache.Options{DefaultNamespaces: map[string]cache.Config{ + "ecosystem": {}, + }}, + WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), + LeaderElectionID: "e3f6c1a7.cloudogu.com", + LivenessEndpointName: "/lifez", + } + + // when + newCtrlOpts, _ := parseFlags(ctrlOpts) + + // then + require.NotEmpty(t, newCtrlOpts) + assert.Equal(t, ":8080", newCtrlOpts.Metrics.BindAddress) + assert.Equal(t, ":8081", newCtrlOpts.HealthProbeBindAddress) + assert.False(t, newCtrlOpts.LeaderElection) + assert.Same(t, ctrlOpts.Scheme, newCtrlOpts.Scheme) + assert.Equal(t, ctrlOpts.Cache, newCtrlOpts.Cache) + assert.Equal(t, ctrlOpts.WebhookServer, newCtrlOpts.WebhookServer) + assert.Equal(t, ctrlOpts.LeaderElectionID, newCtrlOpts.LeaderElectionID) + assert.Equal(t, ctrlOpts.LivenessEndpointName, newCtrlOpts.LivenessEndpointName) +} + func Test_startOperator(t *testing.T) { oldParseFlagsFunc := parseFlags defer func() { parseFlags = oldParseFlagsFunc }() From eec0f68740d390681f08b11ffe828e08c4e1b02c Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Mon, 4 Sep 2023 09:28:35 +0200 Subject: [PATCH 31/37] #1 Fix sonar properties --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 72267e2..0fca687 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,7 +2,7 @@ sonar.projectKey=k8s-backup-operator sonar.projectName=k8s-backup-operator sonar.projectVersion=0.0.0-dev -sonar.go.coverage.reportPaths=target/unit-test/coverage.out,target/k8s-integration-test/report-k8s-integration.out +sonar.go.coverage.reportPaths=target/unit-tests/coverage.out,target/k8s-integration-test/report-k8s-integration.out sonar.go.golangci-lint.reportPaths=target/static-analysis/static-analysis-cs.log sonar.sources=. From ba656767ee32c24501210cf2e32f4257b82a917e Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Mon, 4 Sep 2023 10:12:18 +0200 Subject: [PATCH 32/37] #1 Update ces-build-lib Removes dogu-build-lib --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e02c6b3..84d52ba 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,8 +1,7 @@ #!groovy -@Library(['github.com/cloudogu/dogu-build-lib@v1.6.0', 'github.com/cloudogu/ces-build-lib@1.56.0']) +@Library('github.com/cloudogu/ces-build-lib@1.66.1') import com.cloudogu.ces.cesbuildlib.* -import com.cloudogu.ces.dogubuildlib.* // Creating necessary git objects git = new Git(this, "cesmarvin") From ef503c614b6db145a68980d168668874d6875706 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Mon, 4 Sep 2023 15:29:52 +0200 Subject: [PATCH 33/37] #1 Fix label patching + regenerate CRDs --- Makefile | 10 +- .../crd/bases/k8s.cloudogu.com_backups.yaml | 4 +- config/crd/bases/k8s.cloudogu.com_dogus.yaml | 109 ------------------ .../crd/bases/k8s.cloudogu.com_restores.yaml | 4 +- config/labels/crd_label_patch.yaml | 7 -- config/labels/kustomization.yaml | 10 -- pkg/api/v1/k8s.cloudogu.com_backups.yaml | 55 +++++++++ pkg/api/v1/k8s.cloudogu.com_dogus.yaml | 109 ------------------ pkg/api/v1/k8s.cloudogu.com_restores.yaml | 55 +++++++++ 9 files changed, 117 insertions(+), 246 deletions(-) delete mode 100644 config/crd/bases/k8s.cloudogu.com_dogus.yaml delete mode 100644 config/labels/crd_label_patch.yaml delete mode 100644 config/labels/kustomization.yaml create mode 100644 pkg/api/v1/k8s.cloudogu.com_backups.yaml delete mode 100644 pkg/api/v1/k8s.cloudogu.com_dogus.yaml create mode 100644 pkg/api/v1/k8s.cloudogu.com_restores.yaml diff --git a/Makefile b/Makefile index 0c1f67c..1751f18 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ K8S_PRE_GENERATE_TARGETS=k8s-create-temporary-resource template-dev-only-image-p include build/make/k8s-controller.mk .PHONY: build-boot -build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of the dogu and deploys it into the K8s-EcoSystem. +build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of the operator and deploys it into the K8s-EcoSystem. ##@ Controller specific targets @@ -37,8 +37,8 @@ build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. @echo "Generate manifests..." @$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases - @make template-crd-labels - @cp config/crd/bases/k8s.cloudogu.com_dogus.yaml pkg/api/v1/ + @cp config/crd/bases/k8s.cloudogu.com_backups.yaml pkg/api/v1/ + @cp config/crd/bases/k8s.cloudogu.com_restores.yaml pkg/api/v1/ .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. @@ -56,10 +56,6 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified @$(KUSTOMIZE) build config/crd | kubectl delete --wait=false --ignore-not-found=true -f - @kubectl patch crd/backups.k8s.cloudogu.com -p '{"metadata":{"finalizers":[]}}' --type=merge || true -.PHONY: template-crd-labels -template-crd-labels: kustomize - @$(KUSTOMIZE) build config/labels -o config/crd/bases/k8s.cloudogu.com_dogus.yaml - .PHONY: template-stage template-stage: @echo "Setting STAGE env in deployment to ${STAGE}!" diff --git a/config/crd/bases/k8s.cloudogu.com_backups.yaml b/config/crd/bases/k8s.cloudogu.com_backups.yaml index 86568e6..a0f609f 100644 --- a/config/crd/bases/k8s.cloudogu.com_backups.yaml +++ b/config/crd/bases/k8s.cloudogu.com_backups.yaml @@ -35,7 +35,7 @@ spec: metadata: type: object spec: - description: BackupSpec defines the desired state of Backup + description: Spec defines the desired state of Backup properties: foo: description: Foo is an example field of Backup. Edit backup_types.go @@ -43,7 +43,7 @@ spec: type: string type: object status: - description: BackupStatus defines the observed state of Backup + description: Status defines the observed state of Backup properties: status: type: string diff --git a/config/crd/bases/k8s.cloudogu.com_dogus.yaml b/config/crd/bases/k8s.cloudogu.com_dogus.yaml deleted file mode 100644 index 1d44eab..0000000 --- a/config/crd/bases/k8s.cloudogu.com_dogus.yaml +++ /dev/null @@ -1,109 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - labels: - app: ces - app.kubernetes.io/name: k8s-backup-operator - name: backups.k8s.cloudogu.com -spec: - group: k8s.cloudogu.com - names: - kind: Backup - listKind: BackupList - plural: backups - singular: backup - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: Backup is the Schema for the backups API - 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: BackupSpec defines the desired state of Backup - properties: - foo: - description: Foo is an example field of Backup. Edit backup_types.go - to remove/update - type: string - type: object - status: - description: BackupStatus defines the observed state of Backup - properties: - status: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - labels: - app: ces - app.kubernetes.io/name: k8s-backup-operator - name: restores.k8s.cloudogu.com -spec: - group: k8s.cloudogu.com - names: - kind: Restore - listKind: RestoreList - plural: restores - singular: restore - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: Restore is the Schema for the restores API - 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: RestoreSpec defines the desired state of Restore - properties: - foo: - description: Foo is an example field of Restore. Edit restore_types.go - to remove/update - type: string - type: object - status: - description: RestoreStatus defines the observed state of Restore - properties: - status: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/k8s.cloudogu.com_restores.yaml b/config/crd/bases/k8s.cloudogu.com_restores.yaml index 8e8f2d1..a123b24 100644 --- a/config/crd/bases/k8s.cloudogu.com_restores.yaml +++ b/config/crd/bases/k8s.cloudogu.com_restores.yaml @@ -35,7 +35,7 @@ spec: metadata: type: object spec: - description: RestoreSpec defines the desired state of Restore + description: Spec defines the desired state of Restore properties: foo: description: Foo is an example field of Restore. Edit restore_types.go @@ -43,7 +43,7 @@ spec: type: string type: object status: - description: RestoreStatus defines the observed state of Restore + description: Status defines the observed state of Restore properties: status: type: string diff --git a/config/labels/crd_label_patch.yaml b/config/labels/crd_label_patch.yaml deleted file mode 100644 index 83fabbf..0000000 --- a/config/labels/crd_label_patch.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: backups.k8s.cloudogu.com - labels: - app: ces - app.kubernetes.io/name: k8s-backup-operator diff --git a/config/labels/kustomization.yaml b/config/labels/kustomization.yaml deleted file mode 100644 index 818a199..0000000 --- a/config/labels/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# Labels to add to all resources and selectors. -commonLabels: - app: ces - app.kubernetes.io/name: k8s-backup-operator - -resources: -- ../crd - -patchesStrategicMerge: -- crd_label_patch.yaml diff --git a/pkg/api/v1/k8s.cloudogu.com_backups.yaml b/pkg/api/v1/k8s.cloudogu.com_backups.yaml new file mode 100644 index 0000000..a0f609f --- /dev/null +++ b/pkg/api/v1/k8s.cloudogu.com_backups.yaml @@ -0,0 +1,55 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: backups.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Backup + listKind: BackupList + plural: backups + singular: backup + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Backup is the Schema for the backups API + 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: Spec defines the desired state of Backup + properties: + foo: + description: Foo is an example field of Backup. Edit backup_types.go + to remove/update + type: string + type: object + status: + description: Status defines the observed state of Backup + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/api/v1/k8s.cloudogu.com_dogus.yaml b/pkg/api/v1/k8s.cloudogu.com_dogus.yaml deleted file mode 100644 index 1d44eab..0000000 --- a/pkg/api/v1/k8s.cloudogu.com_dogus.yaml +++ /dev/null @@ -1,109 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - labels: - app: ces - app.kubernetes.io/name: k8s-backup-operator - name: backups.k8s.cloudogu.com -spec: - group: k8s.cloudogu.com - names: - kind: Backup - listKind: BackupList - plural: backups - singular: backup - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: Backup is the Schema for the backups API - 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: BackupSpec defines the desired state of Backup - properties: - foo: - description: Foo is an example field of Backup. Edit backup_types.go - to remove/update - type: string - type: object - status: - description: BackupStatus defines the observed state of Backup - properties: - status: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.13.0 - labels: - app: ces - app.kubernetes.io/name: k8s-backup-operator - name: restores.k8s.cloudogu.com -spec: - group: k8s.cloudogu.com - names: - kind: Restore - listKind: RestoreList - plural: restores - singular: restore - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: Restore is the Schema for the restores API - 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: RestoreSpec defines the desired state of Restore - properties: - foo: - description: Foo is an example field of Restore. Edit restore_types.go - to remove/update - type: string - type: object - status: - description: RestoreStatus defines the observed state of Restore - properties: - status: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/pkg/api/v1/k8s.cloudogu.com_restores.yaml b/pkg/api/v1/k8s.cloudogu.com_restores.yaml new file mode 100644 index 0000000..a123b24 --- /dev/null +++ b/pkg/api/v1/k8s.cloudogu.com_restores.yaml @@ -0,0 +1,55 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + labels: + app: ces + app.kubernetes.io/name: k8s-backup-operator + name: restores.k8s.cloudogu.com +spec: + group: k8s.cloudogu.com + names: + kind: Restore + listKind: RestoreList + plural: restores + singular: restore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Restore is the Schema for the restores API + 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: Spec defines the desired state of Restore + properties: + foo: + description: Foo is an example field of Restore. Edit restore_types.go + to remove/update + type: string + type: object + status: + description: Status defines the observed state of Restore + properties: + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} From c7dc83c4c6794ce6411639f15b4ef88549e08650 Mon Sep 17 00:00:00 2001 From: Robert Auer Date: Tue, 5 Sep 2023 08:27:03 +0200 Subject: [PATCH 34/37] Bump version --- config/manager/kustomization.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index e0b8d8b..fe3abf0 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,8 +1,8 @@ resources: -- manager.yaml + - manager.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: -- name: controller - newName: cloudogu/k8s-backup-operator - newTag: 0.1.0 + - name: controller + newName: cloudogu/k8s-backup-operator + newTag: 0.1.0 From f0a76259e64c8f6cd542b9551f29fba68e726c08 Mon Sep 17 00:00:00 2001 From: Robert Auer Date: Tue, 5 Sep 2023 08:27:37 +0200 Subject: [PATCH 35/37] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e613bc0..20c05dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [v0.1.0] - 2023-09-05 + +Initial release + From 44d43737222ce313c850d4863903c80363912c07 Mon Sep 17 00:00:00 2001 From: Robert Auer Date: Tue, 5 Sep 2023 09:19:02 +0200 Subject: [PATCH 36/37] Merge duplicated Makefile objects in Jenkinsfile --- Jenkinsfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 84d52ba..5042b7c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,6 +13,7 @@ changelog = new Changelog(this) Docker docker = new Docker(this) gpg = new Gpg(this, docker) goVersion = "1.21" +Makefile makefile = new Makefile(this) // Configuration of repository repositoryOwner = "cloudogu" @@ -76,7 +77,6 @@ node('docker') { K3d k3d = new K3d(this, "${WORKSPACE}", "${WORKSPACE}/k3d", env.PATH) try { - Makefile makefile = new Makefile(this) String controllerVersion = makefile.getVersion() stage('Set up k3d cluster') { @@ -134,7 +134,6 @@ void gitWithCredentials(String command) { void stageLintK8SResources() { String kubevalImage = "cytopia/kubeval:0.13" - Makefile makefile = new Makefile(this) String controllerVersion = makefile.getVersion() docker @@ -256,4 +255,4 @@ void stageAutomaticRelease() { void make(String makeArgs) { sh "make ${makeArgs}" -} \ No newline at end of file +} From f28e93b4ba5dd220a819a47ea896b0747ded99e2 Mon Sep 17 00:00:00 2001 From: Robert Auer Date: Tue, 5 Sep 2023 09:37:36 +0200 Subject: [PATCH 37/37] Pass Makefile object to functions that are using it --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5042b7c..47b8aac 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -67,7 +67,7 @@ node('docker') { } stage("Lint k8s Resources") { - stageLintK8SResources() + stageLintK8SResources(makefile) } stage('SonarQube') { @@ -114,7 +114,7 @@ node('docker') { k3d.kubectl("--namespace default wait --for=condition=Ready pods --all") } - stageAutomaticRelease() + stageAutomaticRelease(makefile) } finally { stage('Remove k3d cluster') { k3d.deleteK3d() @@ -132,7 +132,7 @@ void gitWithCredentials(String command) { } } -void stageLintK8SResources() { +void stageLintK8SResources(Makefile makefile) { String kubevalImage = "cytopia/kubeval:0.13" String controllerVersion = makefile.getVersion() @@ -185,7 +185,7 @@ void stageStaticAnalysisSonarQube() { } } -void stageAutomaticRelease() { +void stageAutomaticRelease(Makefile makefile) { if (gitflow.isReleaseBranch()) { String releaseVersion = git.getSimpleBranchName() String dockerReleaseVersion = releaseVersion.split("v")[1]