diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index c15998e7a..000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -* @banzaicloud/supertubes - diff --git a/.github/actions/kind-create/action.yaml b/.github/actions/kind-create/action.yaml index 3e063854f..52e0ddeba 100644 --- a/.github/actions/kind-create/action.yaml +++ b/.github/actions/kind-create/action.yaml @@ -8,7 +8,7 @@ inputs: # adding these parameters to make this reusable later on kind_k8s_version: description: 'The k8s version to use' required: true - default: 'v1.24.15' + default: 'v1.27.3' kind_config: description: 'Path to the kind config to use' required: true @@ -23,7 +23,7 @@ runs: steps: - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - uses: engineerd/setup-kind@v0.5.0 with: name: ${{ inputs.kind_cluster_name }} diff --git a/.github/workflows/build-push-docker.yml b/.github/workflows/build-push-docker.yml new file mode 100644 index 000000000..f561b2592 --- /dev/null +++ b/.github/workflows/build-push-docker.yml @@ -0,0 +1,26 @@ +name: build-publish-docker-image + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get tag name + id: vars + run: echo ::set-output name=tag::${GITHUB_REF:10} + - uses: docker/build-push-action@v1 + if: ${{ !startsWith( steps.vars.outputs.tag, 'kafka-' ) }} + with: + dockerfile: Dockerfile + build_args: VERSION=${{ steps.vars.outputs.tag }},GIT_SHA=${{ github.sha }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + repository: adobe/kafka-operator + tag_with_ref: true + push: ${{ startsWith(github.ref, 'refs/tags/') }} + add_git_labels: true diff --git a/.github/workflows/build-push-kafka-docker.yml b/.github/workflows/build-push-kafka-docker.yml new file mode 100644 index 000000000..54efb3932 --- /dev/null +++ b/.github/workflows/build-push-kafka-docker.yml @@ -0,0 +1,44 @@ +name: build-publish-kafka-docker-image + +on: + push: + tags: + - 'kafka-*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=adobe/kafka + VERSION=latest + if [[ $GITHUB_REF == refs/tags/kafka-* ]]; then + VERSION=${GITHUB_REF#refs/tags/kafka-} + elif [[ $GITHUB_REF == refs/heads/* ]]; then + VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') + fi + TAGS="${DOCKER_IMAGE}:${VERSION}" + echo ::set-output name=version::${VERSION} + echo ::set-output name=tags::${TAGS} + echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ') + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to DockerHub + if: startsWith(github.ref, 'refs/tags/') + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: docker/kafka + push: ${{ startsWith(github.ref, 'refs/tags/') }} + tags: ${{ steps.prep.outputs.tags }} + labels: | + org.opencontainers.image.source=${{ github.event.repository.html_url }} + org.opencontainers.image.created=${{ steps.prep.outputs.created }} + org.opencontainers.image.revision=${{ github.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23a9c3a8c..63d828bcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,12 +13,12 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0 + uses: actions/setup-go@v4 with: - go-version: 1.19 + go-version: 1.21 - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 #v3.5.3 + uses: actions/checkout@v4 - name: Check Go modules dependency file integrity run: | @@ -49,15 +49,15 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0 + uses: actions/setup-go@v4 with: - go-version: 1.19 + go-version: 1.21 - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 #v3.5.3 + uses: actions/checkout@v4 - name: License cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 #v3.3.1 + uses: actions/cache@v3 with: path: .licensei.cache key: license-v1-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..99c6b7266 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '34 23 * * 4' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 395566a1d..000000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Docker -on: - push: - branches: - - master - tags: - - "v?[0-9]+.[0-9]+.[0-9]+" - - "v?[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" - - "v?[0-9]+.[0-9]+.[0-9]+-dev.[0-9]+" -# pull_request: -env: - PLATFORMS: linux/amd64,linux/arm64 -jobs: - docker: - name: Docker - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Cache Docker layers - uses: actions/cache@v3 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.ref }} - restore-keys: | - ${{ runner.os }}-buildx- - - name: Determine tag or commit - uses: haya14busa/action-cond@v1 - id: refortag - with: - cond: ${{ startsWith(github.ref, 'refs/tags/') }} - if_true: ${{ github.ref }} - if_false: latest - - name: Determine image tag - id: imagetag - run: echo "value=${TAG_OR_BRANCH##*/}" >> $GITHUB_OUTPUT - env: - TAG_OR_BRANCH: ${{ steps.refortag.outputs.value }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.CR_PAT }} - - name: Build kafka-operator - uses: docker/build-push-action@v3 - with: - tags: ghcr.io/banzaicloud/kafka-operator:${{ steps.imagetag.outputs.value }} - file: Dockerfile - platforms: ${{ env.PLATFORMS }} - push: true - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.github/workflows/docker_perf_test_load.yml b/.github/workflows/docker_perf_test_load.yml deleted file mode 100644 index a7823cf8a..000000000 --- a/.github/workflows/docker_perf_test_load.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Docker / Performance test load -on: - push: - branches: - - master - tags: - - "koperator-performance-test-load/v?[0-9]+.[0-9]+.[0-9]+" -env: - PLATFORMS: linux/amd64 -jobs: - docker: - name: Docker - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Cache Docker layers - uses: actions/cache@v3 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.ref }} - restore-keys: | - ${{ runner.os }}-buildx- - - - name: Determine tag or commit - uses: haya14busa/action-cond@v1 - id: refortag - with: - cond: ${{ startsWith(github.ref, 'refs/tags/') }} - if_true: ${{ github.ref }} - if_false: latest - - - name: Determine image tag - id: imagetag - run: echo "value=${TAG_OR_BRANCH##*/}" >> $GITHUB_OUTPUT - env: - TAG_OR_BRANCH: ${{ steps.refortag.outputs.value }} - - - name: Setup Docker metadata - id: setup-docker-metadata - uses: docker/metadata-action@v3 - with: - images: ghcr.io/banzaicloud/koperator-performance-test-load - - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.CR_PAT }} - - - name: Build koperator-performance-test-load - uses: docker/build-push-action@v3 - with: - tags: ghcr.io/banzaicloud/koperator-performance-test-load:${{ steps.imagetag.outputs.value }} - file: docs/benchmarks/loadgens/Dockerfile - platforms: ${{ env.PLATFORMS }} - push: true - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.github/workflows/e2e-test.yaml b/.github/workflows/e2e-test.yaml index 484d36248..3d9b0602f 100644 --- a/.github/workflows/e2e-test.yaml +++ b/.github/workflows/e2e-test.yaml @@ -15,12 +15,12 @@ jobs: steps: - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: - go-version: 1.19 + go-version: 1.21 - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build docker image run: | diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index 6db57bc35..f2d49110c 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -8,6 +8,7 @@ on: - "chart/**/[0-9]+.[0-9]+.[0-9]+" - "chart/**/[0-9]+.[0-9]+.[0-9]+-dev.[0-9]+" - "chart/**/[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" + - "chart/**/[0-9]+.[0-9]+.[0-9]+-adobe-[0-9]+" pull_request: env: @@ -24,9 +25,9 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - uses: azure/setup-helm@v1 + - uses: azure/setup-helm@v3 with: version: ${{ env.HELM_VERSION }} @@ -65,13 +66,7 @@ jobs: - name: Set Helm push enabled id: set-helm-push-enabled run: | - HELM_PUSH_ENABLED="" - if [ "${{ github.event_name }}" == "push" ] && echo "${{ steps.set-git-refname.outputs.git_refname }}" | grep -E -q "^chart/${{ env.HELM_CHART_NAME }}/[0-9]+.[0-9]+.[0-9]+**"; then - HELM_PUSH_ENABLED=1 - else - printf >&2 "Unstable chart (%s) from %s event, chart will not be pushed" "${{ steps.set-git-refname.outputs.git_refname }}" "${{ github.event_name }}" - fi - + HELM_PUSH_ENABLED="0" echo "HELM_PUSH_ENABLED=${HELM_PUSH_ENABLED}" echo "helm_push_enabled=${HELM_PUSH_ENABLED}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index c228d5051..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Release - -on: - push: - tags: - - 'v?[0-9]+.[0-9]+.[0-9]+' - - "v?[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" - #- "v?[0-9]+.[0-9]+.[0-9]+-dev.[0-9]+" Disabled for now for dev tags -jobs: - build: - runs-on: ubuntu-latest - - steps: - - - name: Checkout code - uses: actions/checkout@v3 - - - name: Concatenate CRDs - run: | - find config/base/crds/ -name '*.yaml' -maxdepth 1 -exec cat {} + >> kafka-operator.crds.yaml - - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Koperator ${{ github.ref }} - body: | - This release fixes several bug and introduce a couple of new features: - - ## New features: - - TODO - - ## Bug Fixes: - - TODO - - ## Upgrade Notes: - - TODO - - [v#TODO...${{ github.ref }}](https://github.com/banzaicloud/koperator/compare/v#TODO...${{ github.ref }}) - - Thanks for the huge help from the community đŸē - prerelease: false - draft: true - - - name: Upload CRDs - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./kafka-operator.crds.yaml - asset_name: kafka-operator.crds.yaml - asset_content_type: text/plain diff --git a/.golangci.yml b/.golangci.yml index b5eebbcc3..dfe3e1fa0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,7 +2,7 @@ run: deadline: 2m skip-dirs: - client - go: '1.19' + go: '1.21' build-tags: - e2e @@ -88,3 +88,17 @@ linters-settings: lll: # FIXME: we should be able to reduce the length of lines to be closer to the default 120 lines line-length: 300 # default: 120 + depguard: + rules: + main: + files: + - $all + deny: + - pkg: "forbiddenpackage" + desc: Please don't use forbiddenpackage package + +issues: + exclude-rules: + - path: '(.+)_test\.go' + linters: + - goconst diff --git a/Dockerfile b/Dockerfile index 63523f4f7..d4b8b4d54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.19 as builder +FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.21 as builder ARG BUILDPLATFORM ARG TARGETPLATFORM diff --git a/Makefile b/Makefile index ef78467e8..d202e3195 100644 --- a/Makefile +++ b/Makefile @@ -17,14 +17,14 @@ RELEASE_MSG ?= "koperator release" REL_TAG = $(shell ./scripts/increment_version.sh -${RELEASE_TYPE} ${TAG}) -GOLANGCI_VERSION = 1.51.2 -LICENSEI_VERSION = 0.8.0 +GOLANGCI_VERSION = 1.55.2 +LICENSEI_VERSION = 0.9.0 GOPROXY=https://proxy.golang.org -CONTROLLER_GEN_VERSION = v0.9.2 +CONTROLLER_GEN_VERSION = v0.13.0 CONTROLLER_GEN = $(PWD)/bin/controller-gen -ENVTEST_K8S_VERSION = 1.24.x! +ENVTEST_K8S_VERSION = 1.27.x! KUSTOMIZE_BASE = config/overlays/specific-manager-version @@ -85,7 +85,8 @@ install-kustomize: ## Install kustomize. scripts/install_kustomize.sh;\ fi -test: generate fmt vet manifests bin/setup-envtest ## Run unit and integration (non-e2e) tests. +# Run tests +test: generate fmt vet bin/setup-envtest cd api && go test ./... KUBEBUILDER_ASSETS=$$($(BIN_DIR)/setup-envtest --print path --bin-dir $(BIN_DIR) use $(ENVTEST_K8S_VERSION)) \ go test ./... \ @@ -111,7 +112,7 @@ manager: generate fmt vet ## Generate (kubebuilder) and build manager binary. go build -o bin/manager main.go # Run against the configured Kubernetes cluster in ~/.kube/config -run: generate fmt vet manifests ## Run the generated manager against the configured Kubernetes cluster. +run: generate fmt vet go run ./main.go # Install CRDs into a cluster by manually creating or replacing the CRD depending on whether is currently existing @@ -223,7 +224,7 @@ license-header-fix: gen-license-header bin/addlicense ## Fix missing license hea $(ADDLICENSE_OPTS_IGNORE) \ $(ADDLICENSE_SOURCE_DIRS) -GOTEMPLATE_VERSION := 3.7.3 +GOTEMPLATE_VERSION := 3.7.5 bin/gotemplate: $(BIN_DIR)/gotemplate-$(GOTEMPLATE_VERSION) ## Symlink gotemplate- into versionless gotemplate. @ln -sf gotemplate-$(GOTEMPLATE_VERSION) $(BIN_DIR)/gotemplate diff --git a/api/go.mod b/api/go.mod index 55a13bb52..0c6e18b1a 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,21 +1,21 @@ module github.com/banzaicloud/koperator/api -go 1.19 +go 1.21 require ( + dario.cat/mergo v1.0.0 emperror.dev/errors v0.8.1 github.com/banzaicloud/istio-client-go v0.0.17 - github.com/cert-manager/cert-manager v1.11.2 - github.com/imdario/mergo v0.3.13 - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 + github.com/cert-manager/cert-manager v1.13.2 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa gotest.tools v2.2.0+incompatible - k8s.io/api v0.26.4 - k8s.io/apimachinery v0.26.4 - sigs.k8s.io/controller-runtime v0.14.6 + k8s.io/api v0.28.4 + k8s.io/apimachinery v0.28.4 + sigs.k8s.io/controller-runtime v0.16.3 ) require ( - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -23,14 +23,16 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/text v0.7.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) + +// remove once https://github.com/cert-manager/cert-manager/issues/5953 is fixed +replace github.com/Venafi/vcert/v4 => github.com/jetstack/vcert/v4 v4.9.6-0.20230127103832-3aa3dfd6613d diff --git a/api/go.sum b/api/go.sum index bc91b36aa..edef8d7a7 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,16 +1,20 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= -github.com/cert-manager/cert-manager v1.11.2 h1:rJMZv9VtN0YhHZn1esj+V0+KhrYUF8d0BMJWUeIrKX4= -github.com/cert-manager/cert-manager v1.11.2/go.mod h1:hZshV9rYSanOsbRcQHyRmrvhtq/pj0L9+Hg10Do9NgI= +github.com/cert-manager/cert-manager v1.13.2 h1:LG8+OLvxtc49CSyfjW7zHSyvlt7JVaHgRGyhfdvPpkk= +github.com/cert-manager/cert-manager v1.13.2/go.mod h1:AdfSU8muS+bj3C46YaD1VrlpXh672z5MeW/k1k5Sl1w= 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -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/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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.0/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= @@ -19,8 +23,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.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/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +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/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -28,39 +32,47 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +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/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/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 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q= -github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +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.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -68,57 +80,62 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= 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-20201020160332-67f06af15bc9/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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-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-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/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/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= -k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94= -k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= -k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -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.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= +sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +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.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/api/v1alpha1/common_types.go b/api/v1alpha1/common_types.go index 850c1e202..e3132cc70 100644 --- a/api/v1alpha1/common_types.go +++ b/api/v1alpha1/common_types.go @@ -44,6 +44,8 @@ const ( OperationAddBroker CruiseControlTaskOperation = "add_broker" // OperationRemoveBroker means a Cruise Control remove_broker operation OperationRemoveBroker CruiseControlTaskOperation = "remove_broker" + // OperationRemoveDisks means a Cruise Control remove_disks operation + OperationRemoveDisks CruiseControlTaskOperation = "remove_disks" // OperationRebalance means a Cruise Control rebalance operation OperationRebalance CruiseControlTaskOperation = "rebalance" // OperationStatus means a Cruise Control status operation diff --git a/api/v1alpha1/cruisecontroloperation_types.go b/api/v1alpha1/cruisecontroloperation_types.go index 92034d528..4ffeff73c 100644 --- a/api/v1alpha1/cruisecontroloperation_types.go +++ b/api/v1alpha1/cruisecontroloperation_types.go @@ -29,6 +29,9 @@ const ( ErrorPolicyRetry ErrorPolicyType = "retry" // DefaultRetryBackOffDurationSec defines the time between retries of the failed tasks. DefaultRetryBackOffDurationSec = 30 + // PauseLabel defines the label key for pausing Cruise Control operations. + PauseLabel = "pause" + True = "true" ) //+kubebuilder:object:root=true @@ -184,7 +187,7 @@ func (o *CruiseControlOperation) IsDone() bool { } func (o *CruiseControlOperation) IsPaused() bool { - return o.GetLabels()["pause"] == "true" + return o.GetLabels()[PauseLabel] == True } func (o *CruiseControlOperation) IsErrorPolicyIgnore() bool { @@ -221,5 +224,8 @@ func (o *CruiseControlOperation) IsCurrentTaskFinished() bool { func (o *CruiseControlOperation) IsCurrentTaskOperationValid() bool { return o.CurrentTaskOperation() == OperationAddBroker || - o.CurrentTaskOperation() == OperationRebalance || o.CurrentTaskOperation() == OperationRemoveBroker || o.CurrentTaskOperation() == OperationStopExecution + o.CurrentTaskOperation() == OperationRebalance || + o.CurrentTaskOperation() == OperationRemoveBroker || + o.CurrentTaskOperation() == OperationStopExecution || + o.CurrentTaskOperation() == OperationRemoveDisks } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a3b9a6aac..f2aecac6f 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2023 Cisco Systems, Inc. and/or its affiliates diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index 3f226fe4b..c919dfd45 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -66,24 +66,39 @@ type PKIBackend string // CruiseControlVolumeState holds information about the state of volume rebalance type CruiseControlVolumeState string -// IsRunningState returns true if CruiseControlVolumeState indicates -// that the CC operation is scheduled and in-progress -func (s CruiseControlVolumeState) IsRunningState() bool { +// IsDiskRebalanceRunning returns true if CruiseControlVolumeState indicates +// that the CC rebalance disk operation is scheduled and in-progress +func (s CruiseControlVolumeState) IsDiskRebalanceRunning() bool { return s == GracefulDiskRebalanceRunning || s == GracefulDiskRebalanceCompletedWithError || s == GracefulDiskRebalancePaused || s == GracefulDiskRebalanceScheduled } -// IsRequiredState returns true if CruiseControlVolumeState is in GracefulDiskRebalanceRequired state +// IsDiskRemovalRunning returns true if CruiseControlVolumeState indicates +// that the CC remove disks operation is scheduled and in-progress +func (s CruiseControlVolumeState) IsDiskRemovalRunning() bool { + return s == GracefulDiskRemovalRunning || + s == GracefulDiskRemovalCompletedWithError || + s == GracefulDiskRemovalPaused || + s == GracefulDiskRemovalScheduled +} + +// IsRequiredState returns true if CruiseControlVolumeState is in GracefulDiskRebalanceRequired state or GracefulDiskRemovalRequired state func (s CruiseControlVolumeState) IsRequiredState() bool { - return s == GracefulDiskRebalanceRequired + return s == GracefulDiskRebalanceRequired || + s == GracefulDiskRemovalRequired } -// IsActive returns true if CruiseControlVolumeState is in active state +// IsDiskRebalance returns true if CruiseControlVolumeState is in disk rebalance state // the controller needs to take care of. -func (s CruiseControlVolumeState) IsActive() bool { - return s.IsRunningState() || s == GracefulDiskRebalanceRequired +func (s CruiseControlVolumeState) IsDiskRebalance() bool { + return s.IsDiskRebalanceRunning() || s == GracefulDiskRebalanceRequired +} + +// IsDiskRemoval returns true if CruiseControlVolumeState is in disk removal state +func (s CruiseControlVolumeState) IsDiskRemoval() bool { + return s.IsDiskRemovalRunning() || s == GracefulDiskRemovalRequired } // IsUpscale returns true if CruiseControlState in GracefulUpscale* state. @@ -138,11 +153,16 @@ func (r CruiseControlState) IsSucceeded() bool { r == GracefulUpscaleSucceeded } -// IsSucceeded returns true if CruiseControlVolumeState is succeeded -func (r CruiseControlVolumeState) IsSucceeded() bool { +// IsDiskRebalanceSucceeded returns true if CruiseControlVolumeState is disk rebalance succeeded +func (r CruiseControlVolumeState) IsDiskRebalanceSucceeded() bool { return r == GracefulDiskRebalanceSucceeded } +// IsDiskRemovalSucceeded returns true if CruiseControlVolumeState is disk removal succeeded +func (r CruiseControlVolumeState) IsDiskRemovalSucceeded() bool { + return r == GracefulDiskRemovalSucceeded +} + // IsSSL determines if the receiver is using SSL func (r SecurityProtocol) IsSSL() bool { return r.Equal(SecurityProtocolSaslSSL) || r.Equal(SecurityProtocolSSL) @@ -255,6 +275,20 @@ const ( // GracefulDownscalePaused states that the broker downscale task is completed with an error and it will not be retried, it is paused. In this case further downscale tasks can be executed GracefulDownscalePaused CruiseControlState = "GracefulDownscalePaused" + // Disk removal cruise control states + // GracefulDiskRemovalRequired states that the broker volume needs to be removed + GracefulDiskRemovalRequired CruiseControlVolumeState = "GracefulDiskRemovalRequired" + // GracefulDiskRemovalRunning states that for the broker volume a CC disk removal is in progress + GracefulDiskRemovalRunning CruiseControlVolumeState = "GracefulDiskRemovalRunning" + // GracefulDiskRemovalSucceeded states that the for the broker volume removal has succeeded + GracefulDiskRemovalSucceeded CruiseControlVolumeState = "GracefulDiskRemovalSucceeded" + // GracefulDiskRemovalScheduled states that the broker volume removal CCOperation is created and the task is waiting for execution + GracefulDiskRemovalScheduled CruiseControlVolumeState = "GracefulDiskRemovalScheduled" + // GracefulDiskRemovalCompletedWithError states that the broker volume removal task completed with an error + GracefulDiskRemovalCompletedWithError CruiseControlVolumeState = "GracefulDiskRemovalCompletedWithError" + // GracefulDiskRemovalPaused states that the broker volume removal task is completed with an error and it will not be retried, it is paused + GracefulDiskRemovalPaused CruiseControlVolumeState = "GracefulDiskRemovalPaused" + // Disk rebalance cruise control states // GracefulDiskRebalanceRequired states that the broker volume needs a CC disk rebalance GracefulDiskRebalanceRequired CruiseControlVolumeState = "GracefulDiskRebalanceRequired" diff --git a/api/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index 7ac56ad78..99f859ccc 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -16,11 +16,12 @@ package v1beta1 import ( "fmt" + "strconv" "strings" "emperror.dev/errors" - "github.com/imdario/mergo" + "dario.cat/mergo" "github.com/banzaicloud/istio-client-go/pkg/networking/v1beta1" @@ -152,6 +153,8 @@ type KafkaClusterSpec struct { Brokers []Broker `json:"brokers"` DisruptionBudget DisruptionBudget `json:"disruptionBudget,omitempty"` RollingUpgradeConfig RollingUpgradeConfig `json:"rollingUpgradeConfig"` + // Selector for broker pods that need to be recycled/reconciled + TaintedBrokersSelector *metav1.LabelSelector `json:"taintedBrokersSelector,omitempty"` // +kubebuilder:validation:Enum=envoy;istioingress // IngressController specifies the type of the ingress controller to be used for external listeners. The `istioingress` ingress controller type requires the `spec.istioControlPlane` field to be populated as well. IngressController string `json:"ingressController,omitempty"` @@ -211,17 +214,15 @@ type RollingUpgradeConfig struct { // alerts with 'rollingupgrade' FailureThreshold int `json:"failureThreshold"` - // ConcurrentBrokerRestartCountPerRack controls how many brokers can be restarted in parallel during a rolling upgrade. If + // ConcurrentBrokerRestartsAllowed controls how many brokers can be restarted in parallel during a rolling upgrade. If // it is set to a value greater than 1, the operator will restart up to that amount of brokers in parallel, if the // brokers are within the same rack (as specified by "broker.rack" in broker read-only configs). Since using Kafka broker // racks spreads out the replicas, we know that restarting multiple brokers in the same rack will not cause more than // 1/Nth of the replicas of a topic-partition to be unavailable at the same time, where N is the number of racks used. // This is a safe way to speed up the rolling upgrade. Note that for the rack distribution explained above, Cruise Control - // requires `com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal` to be configured. Default value is 1. - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=1 + // requires `com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal` to be configured. // +optional - ConcurrentBrokerRestartCountPerRack int `json:"concurrentBrokerRestartCountPerRack,omitempty"` + ConcurrentBrokerRestartsAllowed int `json:"concurrentBrokerRestartsAllowed,omitempty"` } // DisruptionBudget defines the configuration for PodDisruptionBudget where the workload is managed by the kafka-operator @@ -446,6 +447,8 @@ type EnvoyConfig struct { // If not specified, the Envoy pods' priority is default to zero // +optional PriorityClassName string `json:"priorityClassName,omitempty"` + // Template used to generate broker hostnames for tls enabled envoy. %id will be replaced with brokerId value + BrokerHostnameTemplate string `json:"brokerHostnameTemplate,omitempty"` // EnableHealthCheckHttp10 is a toggle for adding HTTP1.0 support to Envoy health-check, default false // +optional EnableHealthCheckHttp10 bool `json:"enableHealthCheckHttp10,omitempty"` @@ -565,6 +568,16 @@ func (c ExternalListenerConfig) GetIngressControllerTargetPort() int32 { return *c.IngressControllerTargetPort } +// GetBrokerPort - When TLS is enabled AnyCastPort is enough since hostname based multiplexing +// is used and not port based one +func (c ExternalListenerConfig) GetBrokerPort(brokerId int32) int32 { + if c.TLSEnabled() { + return c.GetAnyCastPort() + } else { + return c.ExternalStartingPort + brokerId + } +} + // GetServiceAnnotations returns a copy of the ServiceAnnotations field. func (c IngressServiceSettings) GetServiceAnnotations() map[string]string { return util.CloneMap(c.ServiceAnnotations) @@ -578,6 +591,16 @@ func (c IngressServiceSettings) GetServiceType() corev1.ServiceType { return c.ServiceType } +// Replace %id in brokerHostnameTemplate with actual broker id +func (c EnvoyConfig) GetBrokerHostname(brokerId int32) string { + return strings.Replace(c.BrokerHostnameTemplate, "%id", strconv.Itoa(int(brokerId)), 1) +} + +// We use -1 for ExternalStartingPort value to enable TLS on envoy +func (c ExternalListenerConfig) TLSEnabled() bool { + return c.ExternalStartingPort == -1 +} + // SSLSecrets defines the Kafka SSL secrets type SSLSecrets struct { TLSSecretName string `json:"tlsSecretName"` @@ -633,7 +656,7 @@ type IngressServiceSettings struct { type ExternalListenerConfig struct { CommonListenerSpec `json:",inline"` IngressServiceSettings `json:",inline"` - // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Minimum=-1 // +kubebuilder:validation:Maximum=65535 // externalStartingPort is added to each broker ID to get the port number that will be used for external access to the broker. // The choice of broker ID and externalStartingPort must satisfy 0 < broker ID + externalStartingPort <= 65535 @@ -659,6 +682,8 @@ type ExternalListenerConfig struct { // if set, it overrides the default `KafkaClusterSpec.IstioIngressConfig` or `KafkaClusterSpec.EnvoyConfig` for this external listener. // +optional Config *Config `json:"config,omitempty"` + // TLS secret + TLSSecretName string `json:"tlsSecretName,omitempty"` } // Config defines the external access ingress controller configuration @@ -675,9 +700,16 @@ type IngressConfig struct { // InternalListenerConfig defines the internal listener config for Kafka type InternalListenerConfig struct { - CommonListenerSpec `json:",inline"` - UsedForInnerBrokerCommunication bool `json:"usedForInnerBrokerCommunication"` - UsedForControllerCommunication bool `json:"usedForControllerCommunication,omitempty"` + CommonListenerSpec `json:",inline"` + UsedForControllerCommunication bool `json:"usedForControllerCommunication,omitempty"` + // This following options are helpful when you want to run a Kafka cluster over multiple Kubernetes clusters. + // The broker internal ports are computed as the sum of the internalStartingPort and the broker id. + // +optional + InternalStartingPort int32 `json:"internalStartingPort"` + // If set to a non-empty value, the Kafka brokers will use the external hostname for inter broker communication. + // The internal lister will will share the same hostname with the external listener that is referenced here. + // +optional + ExternalListenerForHostname string `json:"externalListenerForHostname,omitempty"` } // CommonListenerSpec defines the common building block for Listener type @@ -698,6 +730,9 @@ type CommonListenerSpec struct { // +kubebuilder:validation:ExclusiveMinimum=true // +kubebuilder:validation:Maximum=65535 ContainerPort int32 `json:"containerPort"` + // At least one of the listeners should have this flag enabled + // +optional + UsedForInnerBrokerCommunication bool `json:"usedForInnerBrokerCommunication"` } func (c *CommonListenerSpec) GetServerSSLCertSecretName() string { diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index a3e79c9ca..8749f25c0 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2023 Cisco Systems, Inc. and/or its affiliates @@ -23,8 +22,9 @@ package v1beta1 import ( networkingv1beta1 "github.com/banzaicloud/istio-client-go/pkg/networking/v1beta1" - metav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + apismetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -844,6 +844,11 @@ func (in *KafkaClusterSpec) DeepCopyInto(out *KafkaClusterSpec) { } out.DisruptionBudget = in.DisruptionBudget out.RollingUpgradeConfig = in.RollingUpgradeConfig + if in.TaintedBrokersSelector != nil { + in, out := &in.TaintedBrokersSelector, &out.TaintedBrokersSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } if in.IstioControlPlane != nil { in, out := &in.IstioControlPlane, &out.IstioControlPlane *out = new(IstioControlPlaneReference) @@ -966,7 +971,8 @@ func (in *ListenerStatuses) DeepCopyInto(out *ListenerStatuses) { if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make(ListenerStatusList, len(*in)) copy(*out, *in) } @@ -981,7 +987,8 @@ func (in *ListenerStatuses) DeepCopyInto(out *ListenerStatuses) { if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make(ListenerStatusList, len(*in)) copy(*out, *in) } @@ -1126,7 +1133,7 @@ func (in *SSLSecrets) DeepCopyInto(out *SSLSecrets) { *out = *in if in.IssuerRef != nil { in, out := &in.IssuerRef, &out.IssuerRef - *out = new(metav1.ObjectReference) + *out = new(apismetav1.ObjectReference) **out = **in } } diff --git a/charts/kafka-operator/README.md b/charts/kafka-operator/README.md index 172bb93d5..d20628aaf 100644 --- a/charts/kafka-operator/README.md +++ b/charts/kafka-operator/README.md @@ -65,7 +65,7 @@ Parameter | Description | Default `prometheusMetrics.authProxy.serviceAccount.create` | If true, create the service account (see `prometheusMetrics.authProxy.serviceAccount.name`) used by prometheus auth proxy | `true` `prometheusMetrics.authProxy.serviceAccount.name` | ServiceAccount used by prometheus auth proxy | `kafka-operator-authproxy` `prometheusMetrics.authProxy.image.repository` | Auth proxy container image repository | `gcr.io/kubebuilder/kube-rbac-proxy` -`prometheusMetrics.authProxy.image.tag` | Auth proxy container image tag | `v0.13.0` +`prometheusMetrics.authProxy.image.tag` | Auth proxy container image tag | `v0.15.0` `prometheusMetrics.authProxy.image.pullPolicy` | Auth proxy container image pull policy | `IfNotPresent` `rbac.enabled` | Create rbac service account and roles | `true` `imagePullSecrets` | Image pull secrets can be set | `[]` diff --git a/charts/kafka-operator/crds/cruisecontroloperations.yaml b/charts/kafka-operator/crds/cruisecontroloperations.yaml index ef6cc1fa9..c4c1a6bc7 100644 --- a/charts/kafka-operator/crds/cruisecontroloperations.yaml +++ b/charts/kafka-operator/crds/cruisecontroloperations.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: cruisecontroloperations.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/charts/kafka-operator/crds/kafkaclusters.yaml b/charts/kafka-operator/crds/kafkaclusters.yaml index 8ed2611c4..9960dd89c 100644 --- a/charts/kafka-operator/crds/kafkaclusters.yaml +++ b/charts/kafka-operator/crds/kafkaclusters.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkaclusters.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io @@ -1289,7 +1288,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1392,7 +1394,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1476,8 +1481,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -1511,7 +1515,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1686,8 +1693,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -1721,7 +1727,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1811,6 +1820,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -1860,9 +1891,31 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by + the Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container + will have the following effect: this init container + will be continually restarted on exit until all regular + containers have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle differs from + normal init containers and is often referred to as a + "sidecar" container. Although this init container still + starts in the init container sequence, it does not wait + for the container to complete before proceeding to the + next init container. Instead, the next init container + starts immediately after this init container is started, + or after any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -1988,7 +2041,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -2023,16 +2077,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, - if HostProcess is true then HostNetwork must - also be set to true. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if + HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the @@ -2081,8 +2131,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -2116,7 +2165,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2725,7 +2777,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2828,7 +2883,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2912,8 +2970,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -2947,7 +3004,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3122,8 +3182,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -3157,7 +3216,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3247,6 +3309,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -3296,9 +3380,31 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by + the Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container + will have the following effect: this init container + will be continually restarted on exit until all regular + containers have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle differs from + normal init containers and is often referred to as a + "sidecar" container. Although this init container still + starts in the init container sequence, it does not wait + for the container to complete before proceeding to the + next init container. Instead, the next init container + starts immediately after this init container is started, + or after any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -3424,7 +3530,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -3459,16 +3566,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, - if HostProcess is true then HostNetwork must - also be set to true. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if + HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the @@ -3517,8 +3620,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -3552,7 +3654,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3905,8 +4010,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set if type - is "Localhost". + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -3973,16 +4078,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components - that enable the WindowsHostProcessContainers feature - flag. Setting this field without the feature flag - will result in errors when validating the Pod. All - of a Pod's containers must have the same effective - HostProcess value (it is not allowed to have a mix - of HostProcess containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -4047,8 +4148,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -4170,8 +4271,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set if type - is "Localhost". + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -4204,16 +4305,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components - that enable the WindowsHostProcessContainers feature - flag. Setting this field without the feature flag - will result in errors when validating the Pod. All - of a Pod's containers must have the same effective - HostProcess value (it is not allowed to have a mix - of HostProcess containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -4259,7 +4356,7 @@ spec: the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -4426,8 +4523,8 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -4999,7 +5096,7 @@ spec: the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -5231,7 +5328,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -7491,7 +7589,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -7599,7 +7701,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -7686,8 +7792,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -7721,7 +7826,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -7903,8 +8011,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -7938,7 +8045,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -8033,6 +8143,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which + this resource resize policy applies. Supported + values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it + defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -8082,10 +8214,33 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the + container type. Setting the RestartPolicy as "Always" + for the init container will have the following effect: + this init container will be continually restarted + on exit until all regular containers have terminated. + Once all regular containers have completed, all + init containers with restartPolicy "Always" will + be shut down. This lifecycle differs from normal + init containers and is often referred to as a "sidecar" + container. Although this init container still starts + in the init container sequence, it does not wait + for the container to complete before proceeding + to the next init container. Instead, the next init + container starts immediately after this init container + is started, or after any startupProbe has successfully + completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, @@ -8221,8 +8376,9 @@ spec: be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set - if type is "Localhost". + seccomp profile location. Must be set if + type is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind of @@ -8259,17 +8415,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only - be honored by components that enable the - WindowsHostProcessContainers feature flag. - Setting this field without the feature flag - will result in errors when validating the - Pod. All of a Pod's containers must have - the same effective HostProcess value (it - is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + All of a Pod's containers must have the + same effective HostProcess value (it is + not allowed to have a mix of HostProcess + containers and non-HostProcess containers). + In addition, if HostProcess is true then + HostNetwork must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run @@ -8320,8 +8471,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -8355,7 +8505,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -8985,7 +9138,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -9093,7 +9250,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -9180,8 +9341,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9215,7 +9375,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -9397,8 +9560,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9432,7 +9594,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -9527,6 +9692,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which + this resource resize policy applies. Supported + values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it + defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -9576,10 +9763,33 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the + container type. Setting the RestartPolicy as "Always" + for the init container will have the following effect: + this init container will be continually restarted + on exit until all regular containers have terminated. + Once all regular containers have completed, all + init containers with restartPolicy "Always" will + be shut down. This lifecycle differs from normal + init containers and is often referred to as a "sidecar" + container. Although this init container still starts + in the init container sequence, it does not wait + for the container to complete before proceeding + to the next init container. Instead, the next init + container starts immediately after this init container + is started, or after any startupProbe has successfully + completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, @@ -9715,8 +9925,9 @@ spec: be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set - if type is "Localhost". + seccomp profile location. Must be set if + type is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind of @@ -9753,17 +9964,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only - be honored by components that enable the - WindowsHostProcessContainers feature flag. - Setting this field without the feature flag - will result in errors when validating the - Pod. All of a Pod's containers must have - the same effective HostProcess value (it - is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + All of a Pod's containers must have the + same effective HostProcess value (it is + not allowed to have a mix of HostProcess + containers and non-HostProcess containers). + In addition, if HostProcess is true then + HostNetwork must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run @@ -9814,8 +10020,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9849,7 +10054,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -10216,7 +10424,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -10286,15 +10495,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -10362,7 +10567,7 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -10487,7 +10692,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -10520,15 +10726,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -10577,7 +10779,7 @@ spec: specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More - info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -10753,7 +10955,8 @@ spec: Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -11352,7 +11555,7 @@ spec: specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More - info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -11596,7 +11799,8 @@ spec: for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -13880,7 +14084,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -13979,7 +14186,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -14061,8 +14271,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14094,7 +14303,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14269,8 +14480,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14302,7 +14512,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14392,6 +14604,27 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this resource + resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -14440,9 +14673,30 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by the + Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be + continually restarted on exit until all regular containers + have terminated. Once all regular containers have completed, + all init containers with restartPolicy "Always" will be + shut down. This lifecycle differs from normal init containers + and is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe has + successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields of @@ -14567,7 +14821,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -14600,15 +14855,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -14657,8 +14908,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14690,7 +14940,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14993,7 +15245,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -15058,15 +15311,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -15130,7 +15380,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -15250,7 +15501,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -15282,15 +15534,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -15803,7 +16052,7 @@ spec: value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. - More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -16030,7 +16279,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -17916,6 +18166,10 @@ spec: description: Annotations defines the annotations placed on the envoy ingress controller deployment type: object + brokerHostnameTemplate: + description: Template used to generate broker hostnames for tls + enabled envoy. %id will be replaced with brokerId value + type: string disruptionBudget: description: DisruptionBudget is the pod disruption budget attached to Envoy Deployment(s) @@ -18078,7 +18332,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -18143,15 +18398,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -18219,7 +18471,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object serviceAccountName: @@ -18319,14 +18572,19 @@ spec: type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to - select the pods over which spreading will be calculated. + description: "MatchLabelKeys is a set of pod label keys + to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading - will be calculated for the incoming pod. Keys that don't - exist in the incoming pod labels will be ignored. A null - or empty list means only match against labelSelector. + will be calculated for the incoming pod. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't + set. Keys that don't exist in the incoming pod labels + will be ignored. A null or empty list means only match + against labelSelector. \n This is a beta field and requires + the MatchLabelKeysInPodTopologySpread feature gate to + be enabled (enabled by default)." items: type: string type: array @@ -18845,7 +19103,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object tolerations: @@ -20180,6 +20439,11 @@ spec: description: Annotations defines the annotations placed on the envoy ingress controller deployment type: object + brokerHostnameTemplate: + description: Template used to generate broker + hostnames for tls enabled envoy. %id will + be replaced with brokerId value + type: string disruptionBudget: description: DisruptionBudget is the pod disruption budget attached to Envoy Deployment(s) @@ -20375,8 +20639,9 @@ spec: must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only - be set if type is "Localhost". + seccomp profile location. Must be + set if type is "Localhost". Must + NOT be set for any other type. type: string type: description: "type indicates which @@ -20460,18 +20725,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as - a 'Host Process' container. This - field is alpha-level and will only - be honored by components that enable - the WindowsHostProcessContainers - feature flag. Setting this field - without the feature flag will result - in errors when validating the Pod. - All of a Pod's containers must have + a 'Host Process' container. All + of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean @@ -20552,7 +20811,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object serviceAccountName: @@ -20681,7 +20941,7 @@ spec: type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: MatchLabelKeys is a set + description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values @@ -20689,10 +20949,17 @@ spec: key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated - for the incoming pod. Keys that don't - exist in the incoming pod labels will - be ignored. A null or empty list means - only match against labelSelector. + for the incoming pod. The same key + is forbidden to exist in both MatchLabelKeys + and LabelSelector. MatchLabelKeys + cannot be set when LabelSelector isn't + set. Keys that don't exist in the + incoming pod labels will be ignored. + A null or empty list means only match + against labelSelector. \n This is + a beta field and requires the MatchLabelKeysInPodTopologySpread + feature gate to be enabled (enabled + by default)." items: type: string type: array @@ -21196,7 +21463,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object tolerations: @@ -21289,7 +21557,7 @@ spec: controller format: int32 maximum: 65535 - minimum: 0 + minimum: -1 type: integer externalTrafficPolicy: description: externalTrafficPolicy denotes if this Service @@ -21362,6 +21630,9 @@ spec: - requested - none type: string + tlsSecretName: + description: TLS secret + type: string type: description: 'SecurityProtocol is the protocol used to communicate with brokers. Valid values are: plaintext, ssl, sasl_plaintext, @@ -21372,6 +21643,10 @@ spec: - sasl_ssl - sasl_plaintext type: string + usedForInnerBrokerCommunication: + description: At least one of the listeners should have this + flag enabled + type: boolean required: - containerPort - externalStartingPort @@ -21390,6 +21665,19 @@ spec: maximum: 65535 minimum: 0 type: integer + externalListenerForHostname: + description: If set to a non-empty value, the Kafka brokers + will use the external hostname for inter broker communication. + The internal lister will will share the same hostname + with the external listener that is referenced here. + type: string + internalStartingPort: + description: This following options are helpful when you + want to run a Kafka cluster over multiple Kubernetes clusters. + The broker internal ports are computed as the sum of the + internalStartingPort and the broker id. + format: int32 + type: integer name: pattern: ^[a-z0-9\-]+ type: string @@ -21432,12 +21720,13 @@ spec: usedForControllerCommunication: type: boolean usedForInnerBrokerCommunication: + description: At least one of the listeners should have this + flag enabled type: boolean required: - containerPort - name - type - - usedForInnerBrokerCommunication type: object type: array serviceAnnotations: @@ -21526,10 +21815,9 @@ spec: description: RollingUpgradeConfig defines the desired config of the RollingUpgrade properties: - concurrentBrokerRestartCountPerRack: - default: 1 - description: ConcurrentBrokerRestartCountPerRack controls how - many brokers can be restarted in parallel during a rolling upgrade. + concurrentBrokerRestartsAllowed: + description: ConcurrentBrokerRestartsAllowed controls how many + brokers can be restarted in parallel during a rolling upgrade. If it is set to a value greater than 1, the operator will restart up to that amount of brokers in parallel, if the brokers are within the same rack (as specified by "broker.rack" in broker @@ -21540,8 +21828,7 @@ spec: N is the number of racks used. This is a safe way to speed up the rolling upgrade. Note that for the rack distribution explained above, Cruise Control requires `com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal` - to be configured. Default value is 1. - minimum: 1 + to be configured. type: integer failureThreshold: description: FailureThreshold controls how many failures the cluster @@ -21554,6 +21841,51 @@ spec: required: - failureThreshold type: object + taintedBrokersSelector: + description: Selector for broker pods that need to be recycled/reconciled + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship to + a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic zkAddresses: description: ZKAddresses specifies the ZooKeeper connection string in the form hostname:port where host and port are the host and port diff --git a/charts/kafka-operator/crds/kafkatopics.yaml b/charts/kafka-operator/crds/kafkatopics.yaml index 3dacb7248..ca2e1d890 100644 --- a/charts/kafka-operator/crds/kafkatopics.yaml +++ b/charts/kafka-operator/crds/kafkatopics.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkatopics.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/charts/kafka-operator/crds/kafkausers.yaml b/charts/kafka-operator/crds/kafkausers.yaml index 7fa02b70e..371f2bc0b 100644 --- a/charts/kafka-operator/crds/kafkausers.yaml +++ b/charts/kafka-operator/crds/kafkausers.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkausers.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/charts/kafka-operator/values.yaml b/charts/kafka-operator/values.yaml index 83698e8db..a01c18585 100644 --- a/charts/kafka-operator/values.yaml +++ b/charts/kafka-operator/values.yaml @@ -67,7 +67,7 @@ prometheusMetrics: enabled: true image: repository: gcr.io/kubebuilder/kube-rbac-proxy - tag: v0.13.0 + tag: v0.15.0 pullPolicy: IfNotPresent serviceAccount: create: true diff --git a/config/base/crds/kafka.banzaicloud.io_cruisecontroloperations.yaml b/config/base/crds/kafka.banzaicloud.io_cruisecontroloperations.yaml index ef6cc1fa9..c4c1a6bc7 100644 --- a/config/base/crds/kafka.banzaicloud.io_cruisecontroloperations.yaml +++ b/config/base/crds/kafka.banzaicloud.io_cruisecontroloperations.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: cruisecontroloperations.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml index 8ed2611c4..9960dd89c 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkaclusters.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io @@ -1289,7 +1288,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1392,7 +1394,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1476,8 +1481,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -1511,7 +1515,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1686,8 +1693,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -1721,7 +1727,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -1811,6 +1820,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -1860,9 +1891,31 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by + the Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container + will have the following effect: this init container + will be continually restarted on exit until all regular + containers have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle differs from + normal init containers and is often referred to as a + "sidecar" container. Although this init container still + starts in the init container sequence, it does not wait + for the container to complete before proceeding to the + next init container. Instead, the next init container + starts immediately after this init container is started, + or after any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -1988,7 +2041,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -2023,16 +2077,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, - if HostProcess is true then HostNetwork must - also be set to true. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if + HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the @@ -2081,8 +2131,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -2116,7 +2165,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2725,7 +2777,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2828,7 +2883,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -2912,8 +2970,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -2947,7 +3004,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3122,8 +3182,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -3157,7 +3216,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3247,6 +3309,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this + resource resize policy applies. Supported values: + cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -3296,9 +3380,31 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by + the Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container + will have the following effect: this init container + will be continually restarted on exit until all regular + containers have terminated. Once all regular containers + have completed, all init containers with restartPolicy + "Always" will be shut down. This lifecycle differs from + normal init containers and is often referred to as a + "sidecar" container. Although this init container still + starts in the init container sequence, it does not wait + for the container to complete before proceeding to the + next init container. Instead, the next init container + starts immediately after this init container is started, + or after any startupProbe has successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields @@ -3424,7 +3530,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -3459,16 +3566,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the - feature flag will result in errors when validating - the Pod. All of a Pod's containers must have - the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, - if HostProcess is true then HostNetwork must - also be set to true. + All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and + non-HostProcess containers). In addition, if + HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the @@ -3517,8 +3620,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a - GRPC port. This is a beta field and requires enabling - GRPCContainerProbe feature gate. + GRPC port. properties: port: description: Port number of the gRPC service. @@ -3552,7 +3654,10 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -3905,8 +4010,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set if type - is "Localhost". + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -3973,16 +4078,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components - that enable the WindowsHostProcessContainers feature - flag. Setting this field without the feature flag - will result in errors when validating the Pod. All - of a Pod's containers must have the same effective - HostProcess value (it is not allowed to have a mix - of HostProcess containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -4047,8 +4148,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -4170,8 +4271,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set if type - is "Localhost". + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -4204,16 +4305,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components - that enable the WindowsHostProcessContainers feature - flag. Setting this field without the feature flag - will result in errors when validating the Pod. All - of a Pod's containers must have the same effective - HostProcess value (it is not allowed to have a mix - of HostProcess containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -4259,7 +4356,7 @@ spec: the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -4426,8 +4523,8 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -4999,7 +5096,7 @@ spec: the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -5231,7 +5328,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -7491,7 +7589,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -7599,7 +7701,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -7686,8 +7792,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -7721,7 +7826,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -7903,8 +8011,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -7938,7 +8045,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -8033,6 +8143,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which + this resource resize policy applies. Supported + values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it + defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -8082,10 +8214,33 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the + container type. Setting the RestartPolicy as "Always" + for the init container will have the following effect: + this init container will be continually restarted + on exit until all regular containers have terminated. + Once all regular containers have completed, all + init containers with restartPolicy "Always" will + be shut down. This lifecycle differs from normal + init containers and is often referred to as a "sidecar" + container. Although this init container still starts + in the init container sequence, it does not wait + for the container to complete before proceeding + to the next init container. Instead, the next init + container starts immediately after this init container + is started, or after any startupProbe has successfully + completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, @@ -8221,8 +8376,9 @@ spec: be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set - if type is "Localhost". + seccomp profile location. Must be set if + type is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind of @@ -8259,17 +8415,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only - be honored by components that enable the - WindowsHostProcessContainers feature flag. - Setting this field without the feature flag - will result in errors when validating the - Pod. All of a Pod's containers must have - the same effective HostProcess value (it - is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + All of a Pod's containers must have the + same effective HostProcess value (it is + not allowed to have a mix of HostProcess + containers and non-HostProcess containers). + In addition, if HostProcess is true then + HostNetwork must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run @@ -8320,8 +8471,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -8355,7 +8505,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -8985,7 +9138,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -9093,7 +9250,11 @@ spec: custom header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon + output, so case-variant names + will be understood as the same + header. type: string value: description: The header field value @@ -9180,8 +9341,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9215,7 +9375,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -9397,8 +9560,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9432,7 +9594,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -9527,6 +9692,28 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which + this resource resize policy applies. Supported + values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it + defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -9576,10 +9763,33 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to - an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + an implementation-defined value. Requests cannot + exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may + only be set for init containers, and the only allowed + value is "Always". For non-init containers or when + this field is not specified, the restart behavior + is defined by the Pod''s restart policy and the + container type. Setting the RestartPolicy as "Always" + for the init container will have the following effect: + this init container will be continually restarted + on exit until all regular containers have terminated. + Once all regular containers have completed, all + init containers with restartPolicy "Always" will + be shut down. This lifecycle differs from normal + init containers and is often referred to as a "sidecar" + container. Although this init container still starts + in the init container sequence, it does not wait + for the container to complete before proceeding + to the next init container. Instead, the next init + container starts immediately after this init container + is started, or after any startupProbe has successfully + completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, @@ -9715,8 +9925,9 @@ spec: be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only be set - if type is "Localhost". + seccomp profile location. Must be set if + type is "Localhost". Must NOT be set for + any other type. type: string type: description: "type indicates which kind of @@ -9753,17 +9964,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as a 'Host Process' container. - This field is alpha-level and will only - be honored by components that enable the - WindowsHostProcessContainers feature flag. - Setting this field without the feature flag - will result in errors when validating the - Pod. All of a Pod's containers must have - the same effective HostProcess value (it - is not allowed to have a mix of HostProcess - containers and non-HostProcess containers). In - addition, if HostProcess is true then HostNetwork - must also be set to true. + All of a Pod's containers must have the + same effective HostProcess value (it is + not allowed to have a mix of HostProcess + containers and non-HostProcess containers). + In addition, if HostProcess is true then + HostNetwork must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run @@ -9814,8 +10020,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving - a GRPC port. This is a beta field and requires - enabling GRPCContainerProbe feature gate. + a GRPC port. properties: port: description: Port number of the gRPC service. @@ -9849,7 +10054,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. + This will be canonicalized upon output, + so case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -10216,7 +10424,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -10286,15 +10495,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -10362,7 +10567,7 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -10487,7 +10692,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -10520,15 +10726,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -10577,7 +10779,7 @@ spec: specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More - info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -10753,7 +10955,8 @@ spec: Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -11352,7 +11555,7 @@ spec: specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More - info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -11596,7 +11799,8 @@ spec: for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -13880,7 +14084,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -13979,7 +14186,10 @@ spec: header to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This + will be canonicalized upon output, so + case-variant names will be understood + as the same header. type: string value: description: The header field value @@ -14061,8 +14271,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14094,7 +14303,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14269,8 +14480,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14302,7 +14512,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14392,6 +14604,27 @@ spec: format: int32 type: integer type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource + resize policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this resource + resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified + resource is resized. If not specified, it defaults + to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' @@ -14440,9 +14673,30 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + restartPolicy: + description: 'RestartPolicy defines the restart behavior + of individual containers in a pod. This field may only + be set for init containers, and the only allowed value + is "Always". For non-init containers or when this field + is not specified, the restart behavior is defined by the + Pod''s restart policy and the container type. Setting + the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be + continually restarted on exit until all regular containers + have terminated. Once all regular containers have completed, + all init containers with restartPolicy "Always" will be + shut down. This lifecycle differs from normal init containers + and is often referred to as a "sidecar" container. Although + this init container still starts in the init container + sequence, it does not wait for the container to complete + before proceeding to the next init container. Instead, + the next init container starts immediately after this + init container is started, or after any startupProbe has + successfully completed.' + type: string securityContext: description: 'SecurityContext defines the security options the container should be run with. If set, the fields of @@ -14567,7 +14821,8 @@ spec: The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must only be set if type is "Localhost". + Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp @@ -14600,15 +14855,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container - should be run as a 'Host Process' container. This - field is alpha-level and will only be honored - by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature - flag will result in errors when validating the - Pod. All of a Pod's containers must have the same - effective HostProcess value (it is not allowed - to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess is true + should be run as a 'Host Process' container. All + of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a + mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean runAsUserName: @@ -14657,8 +14908,7 @@ spec: type: integer grpc: description: GRPC specifies an action involving a GRPC - port. This is a beta field and requires enabling GRPCContainerProbe - feature gate. + port. properties: port: description: Port number of the gRPC service. Number @@ -14690,7 +14940,9 @@ spec: to be used in HTTP probes properties: name: - description: The header field name + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. type: string value: description: The header field value @@ -14993,7 +15245,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -15058,15 +15311,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -15130,7 +15380,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -15250,7 +15501,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -15282,15 +15534,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -15803,7 +16052,7 @@ spec: value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. - More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -16030,7 +16279,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: @@ -17916,6 +18166,10 @@ spec: description: Annotations defines the annotations placed on the envoy ingress controller deployment type: object + brokerHostnameTemplate: + description: Template used to generate broker hostnames for tls + enabled envoy. %id will be replaced with brokerId value + type: string disruptionBudget: description: DisruptionBudget is the pod disruption budget attached to Envoy Deployment(s) @@ -18078,7 +18332,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -18143,15 +18398,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -18219,7 +18471,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object serviceAccountName: @@ -18319,14 +18572,19 @@ spec: type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to - select the pods over which spreading will be calculated. + description: "MatchLabelKeys is a set of pod label keys + to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading - will be calculated for the incoming pod. Keys that don't - exist in the incoming pod labels will be ignored. A null - or empty list means only match against labelSelector. + will be calculated for the incoming pod. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't + set. Keys that don't exist in the incoming pod labels + will be ignored. A null or empty list means only match + against labelSelector. \n This is a beta field and requires + the MatchLabelKeysInPodTopologySpread feature gate to + be enabled (enabled by default)." items: type: string type: array @@ -18845,7 +19103,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object tolerations: @@ -20180,6 +20439,11 @@ spec: description: Annotations defines the annotations placed on the envoy ingress controller deployment type: object + brokerHostnameTemplate: + description: Template used to generate broker + hostnames for tls enabled envoy. %id will + be replaced with brokerId value + type: string disruptionBudget: description: DisruptionBudget is the pod disruption budget attached to Envoy Deployment(s) @@ -20375,8 +20639,9 @@ spec: must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured - seccomp profile location. Must only - be set if type is "Localhost". + seccomp profile location. Must be + set if type is "Localhost". Must + NOT be set for any other type. type: string type: description: "type indicates which @@ -20460,18 +20725,12 @@ spec: hostProcess: description: HostProcess determines if a container should be run as - a 'Host Process' container. This - field is alpha-level and will only - be honored by components that enable - the WindowsHostProcessContainers - feature flag. Setting this field - without the feature flag will result - in errors when validating the Pod. - All of a Pod's containers must have + a 'Host Process' container. All + of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess - containers). In addition, if HostProcess + containers). In addition, if HostProcess is true then HostNetwork must also be set to true. type: boolean @@ -20552,7 +20811,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object serviceAccountName: @@ -20681,7 +20941,7 @@ spec: type: object x-kubernetes-map-type: atomic matchLabelKeys: - description: MatchLabelKeys is a set + description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values @@ -20689,10 +20949,17 @@ spec: key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated - for the incoming pod. Keys that don't - exist in the incoming pod labels will - be ignored. A null or empty list means - only match against labelSelector. + for the incoming pod. The same key + is forbidden to exist in both MatchLabelKeys + and LabelSelector. MatchLabelKeys + cannot be set when LabelSelector isn't + set. Keys that don't exist in the + incoming pod labels will be ignored. + A null or empty list means only match + against labelSelector. \n This is + a beta field and requires the MatchLabelKeysInPodTopologySpread + feature gate to be enabled (enabled + by default)." items: type: string type: array @@ -21196,7 +21463,8 @@ spec: If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object tolerations: @@ -21289,7 +21557,7 @@ spec: controller format: int32 maximum: 65535 - minimum: 0 + minimum: -1 type: integer externalTrafficPolicy: description: externalTrafficPolicy denotes if this Service @@ -21362,6 +21630,9 @@ spec: - requested - none type: string + tlsSecretName: + description: TLS secret + type: string type: description: 'SecurityProtocol is the protocol used to communicate with brokers. Valid values are: plaintext, ssl, sasl_plaintext, @@ -21372,6 +21643,10 @@ spec: - sasl_ssl - sasl_plaintext type: string + usedForInnerBrokerCommunication: + description: At least one of the listeners should have this + flag enabled + type: boolean required: - containerPort - externalStartingPort @@ -21390,6 +21665,19 @@ spec: maximum: 65535 minimum: 0 type: integer + externalListenerForHostname: + description: If set to a non-empty value, the Kafka brokers + will use the external hostname for inter broker communication. + The internal lister will will share the same hostname + with the external listener that is referenced here. + type: string + internalStartingPort: + description: This following options are helpful when you + want to run a Kafka cluster over multiple Kubernetes clusters. + The broker internal ports are computed as the sum of the + internalStartingPort and the broker id. + format: int32 + type: integer name: pattern: ^[a-z0-9\-]+ type: string @@ -21432,12 +21720,13 @@ spec: usedForControllerCommunication: type: boolean usedForInnerBrokerCommunication: + description: At least one of the listeners should have this + flag enabled type: boolean required: - containerPort - name - type - - usedForInnerBrokerCommunication type: object type: array serviceAnnotations: @@ -21526,10 +21815,9 @@ spec: description: RollingUpgradeConfig defines the desired config of the RollingUpgrade properties: - concurrentBrokerRestartCountPerRack: - default: 1 - description: ConcurrentBrokerRestartCountPerRack controls how - many brokers can be restarted in parallel during a rolling upgrade. + concurrentBrokerRestartsAllowed: + description: ConcurrentBrokerRestartsAllowed controls how many + brokers can be restarted in parallel during a rolling upgrade. If it is set to a value greater than 1, the operator will restart up to that amount of brokers in parallel, if the brokers are within the same rack (as specified by "broker.rack" in broker @@ -21540,8 +21828,7 @@ spec: N is the number of racks used. This is a safe way to speed up the rolling upgrade. Note that for the rack distribution explained above, Cruise Control requires `com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal` - to be configured. Default value is 1. - minimum: 1 + to be configured. type: integer failureThreshold: description: FailureThreshold controls how many failures the cluster @@ -21554,6 +21841,51 @@ spec: required: - failureThreshold type: object + taintedBrokersSelector: + description: Selector for broker pods that need to be recycled/reconciled + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship to + a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic zkAddresses: description: ZKAddresses specifies the ZooKeeper connection string in the form hostname:port where host and port are the host and port diff --git a/config/base/crds/kafka.banzaicloud.io_kafkatopics.yaml b/config/base/crds/kafka.banzaicloud.io_kafkatopics.yaml index 3dacb7248..ca2e1d890 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkatopics.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkatopics.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkatopics.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/config/base/crds/kafka.banzaicloud.io_kafkausers.yaml b/config/base/crds/kafka.banzaicloud.io_kafkausers.yaml index 7fa02b70e..371f2bc0b 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkausers.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkausers.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: kafkausers.kafka.banzaicloud.io spec: group: kafka.banzaicloud.io diff --git a/config/base/rbac/role.yaml b/config/base/rbac/role.yaml index 6b4a6e8dc..fd829ef12 100644 --- a/config/base/rbac/role.yaml +++ b/config/base/rbac/role.yaml @@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: manager-role rules: - apiGroups: diff --git a/config/base/webhook/manifests.yaml b/config/base/webhook/manifests.yaml index 33f5dd50f..a0cffb84d 100644 --- a/config/base/webhook/manifests.yaml +++ b/config/base/webhook/manifests.yaml @@ -2,7 +2,6 @@ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - creationTimestamp: null name: validating-webhook-configuration webhooks: - admissionReviewVersions: diff --git a/config/overlays/auth-proxy-enabled/manager_auth_proxy_patch.yaml b/config/overlays/auth-proxy-enabled/manager_auth_proxy_patch.yaml index 3814ad2dd..fc4fb1ea3 100644 --- a/config/overlays/auth-proxy-enabled/manager_auth_proxy_patch.yaml +++ b/config/overlays/auth-proxy-enabled/manager_auth_proxy_patch.yaml @@ -10,7 +10,7 @@ spec: spec: containers: - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 args: - "--secure-listen-address=0.0.0.0:8443" - "--upstream=http://127.0.0.1:8080/" diff --git a/config/overlays/certmanager-with-auth-proxy/auth-proxy/manager_auth_proxy_patch.yaml b/config/overlays/certmanager-with-auth-proxy/auth-proxy/manager_auth_proxy_patch.yaml index 8f292f1fb..67185b3f1 100644 --- a/config/overlays/certmanager-with-auth-proxy/auth-proxy/manager_auth_proxy_patch.yaml +++ b/config/overlays/certmanager-with-auth-proxy/auth-proxy/manager_auth_proxy_patch.yaml @@ -10,7 +10,7 @@ spec: spec: containers: - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 args: - "--secure-listen-address=0.0.0.0:8443" - "--upstream=http://127.0.0.1:8080/" diff --git a/controllers/cruisecontroloperation_controller.go b/controllers/cruisecontroloperation_controller.go index 9a5db907e..56eaedb1c 100644 --- a/controllers/cruisecontroloperation_controller.go +++ b/controllers/cruisecontroloperation_controller.go @@ -55,8 +55,9 @@ const ( var ( defaultRequeueIntervalInSeconds = 10 executionPriorityMap = map[banzaiv1alpha1.CruiseControlTaskOperation]int{ - banzaiv1alpha1.OperationAddBroker: 2, - banzaiv1alpha1.OperationRemoveBroker: 1, + banzaiv1alpha1.OperationAddBroker: 3, + banzaiv1alpha1.OperationRemoveBroker: 2, + banzaiv1alpha1.OperationRemoveDisks: 1, banzaiv1alpha1.OperationRebalance: 0, } missingCCResErr = errors.New("missing Cruise Control user task result") @@ -153,7 +154,7 @@ func (r *CruiseControlOperationReconciler) Reconcile(ctx context.Context, reques } // Checking Cruise Control health - status, err := r.getStatus(ctx, log, kafkaCluster, ccOperationListClusterWide) + status, err := r.getStatus(ctx, log, kafkaCluster, kafkaClusterRef, ccOperationListClusterWide) if err != nil { log.Error(err, "could not get Cruise Control status") return requeueAfter(defaultRequeueIntervalInSeconds) @@ -206,7 +207,11 @@ func (r *CruiseControlOperationReconciler) Reconcile(ctx context.Context, reques return reconciled() } - ccOperationExecution := selectOperationForExecution(ccOperationQueueMap) + ccOperationExecution, err := r.selectOperationForExecution(ccOperationQueueMap) + if err != nil { + log.Error(err, "requeue event as selecting operation for execution failed") + return requeueAfter(defaultRequeueIntervalInSeconds) + } // There is nothing to be executed for now, requeue if ccOperationExecution == nil { return requeueAfter(defaultRequeueIntervalInSeconds) @@ -274,6 +279,8 @@ func (r *CruiseControlOperationReconciler) executeOperation(ctx context.Context, cruseControlTaskResult, err = r.scaler.RemoveBrokersWithParams(ctx, ccOperationExecution.CurrentTaskParameters()) case banzaiv1alpha1.OperationRebalance: cruseControlTaskResult, err = r.scaler.RebalanceWithParams(ctx, ccOperationExecution.CurrentTaskParameters()) + case banzaiv1alpha1.OperationRemoveDisks: + cruseControlTaskResult, err = r.scaler.RemoveDisksWithParams(ctx, ccOperationExecution.CurrentTaskParameters()) case banzaiv1alpha1.OperationStopExecution: cruseControlTaskResult, err = r.scaler.StopExecution(ctx) case banzaiv1alpha1.OperationStatus: @@ -311,29 +318,56 @@ func sortOperations(ccOperations []*banzaiv1alpha1.CruiseControlOperation) map[s return ccOperationQueueMap } -func selectOperationForExecution(ccOperationQueueMap map[string][]*banzaiv1alpha1.CruiseControlOperation) *banzaiv1alpha1.CruiseControlOperation { - // SELECTING OPERATION FOR EXECUTION - var ccOperationExecution *banzaiv1alpha1.CruiseControlOperation +// selectOperationForExecution selects the next operation to be executed +func (r *CruiseControlOperationReconciler) selectOperationForExecution(ccOperationQueueMap map[string][]*banzaiv1alpha1.CruiseControlOperation) (*banzaiv1alpha1.CruiseControlOperation, error) { // First prio: execute the finalize task - switch { - case len(ccOperationQueueMap[ccOperationForStopExecution]) > 0: - ccOperationExecution = ccOperationQueueMap[ccOperationForStopExecution][0] - ccOperationExecution.CurrentTask().Operation = banzaiv1alpha1.OperationStopExecution + if op := getFirstOperation(ccOperationQueueMap, ccOperationForStopExecution); op != nil { + op.CurrentTask().Operation = banzaiv1alpha1.OperationStopExecution + return op, nil + } + // Second prio: execute add_broker operation - case len(ccOperationQueueMap[ccOperationFirstExecution]) > 0 && ccOperationQueueMap[ccOperationFirstExecution][0].CurrentTaskOperation() == banzaiv1alpha1.OperationAddBroker: - ccOperationExecution = ccOperationQueueMap[ccOperationFirstExecution][0] + if op := getFirstOperation(ccOperationQueueMap, ccOperationFirstExecution); op != nil && + op.CurrentTaskOperation() == banzaiv1alpha1.OperationAddBroker { + return op, nil + } + // Third prio: execute failed task - case len(ccOperationQueueMap[ccOperationRetryExecution]) > 0: + if op := getFirstOperation(ccOperationQueueMap, ccOperationRetryExecution); op != nil { + // If there is a failed remove_disks task and there is a rebalance_disks task in the queue, we execute the rebalance_disks task + // This could only happen if the user tried to delete a disk, and later rolled back the change + if op.CurrentTaskOperation() == banzaiv1alpha1.OperationRemoveDisks { + for _, opFirstExecution := range ccOperationQueueMap[ccOperationFirstExecution] { + if opFirstExecution.CurrentTaskOperation() == banzaiv1alpha1.OperationRebalance { + // Mark the remove disk operation as paused, so it is not retried + op.Labels[banzaiv1alpha1.PauseLabel] = True + err := r.Client.Update(context.TODO(), op) + if err != nil { + return nil, errors.WrapIfWithDetails(err, "failed to update Cruise Control operation", "name", op.Name, "namespace", op.Namespace) + } + + // Execute the rebalance disks operation + return opFirstExecution, nil + } + } + } + // When the default backoff duration elapsed we retry - if ccOperationQueueMap[ccOperationRetryExecution][0].IsReadyForRetryExecution() { - ccOperationExecution = ccOperationQueueMap[ccOperationRetryExecution][0] + if op.IsReadyForRetryExecution() { + return op, nil } - // Forth prio: execute the first element in the FirstExecutionQueue which is ordered by operation type and k8s creation timestamp - case len(ccOperationQueueMap[ccOperationFirstExecution]) > 0: - ccOperationExecution = ccOperationQueueMap[ccOperationFirstExecution][0] } - return ccOperationExecution + // Fourth prio: execute the first element in the FirstExecutionQueue which is ordered by operation type and k8s creation timestamp + return getFirstOperation(ccOperationQueueMap, ccOperationFirstExecution), nil +} + +// getFirstOperation returns the first operation in the given queue +func getFirstOperation(ccOperationQueueMap map[string][]*banzaiv1alpha1.CruiseControlOperation, key string) *banzaiv1alpha1.CruiseControlOperation { + if len(ccOperationQueueMap[key]) > 0 { + return ccOperationQueueMap[key][0] + } + return nil } // SetupCruiseControlWithManager registers cruise control controller to the manager @@ -491,6 +525,7 @@ func (r *CruiseControlOperationReconciler) getStatus( ctx context.Context, log logr.Logger, kafkaCluster *banzaiv1beta1.KafkaCluster, + kafkaClusterRef client.ObjectKey, ccOperationListClusterWide banzaiv1alpha1.CruiseControlOperationList, ) (scale.CruiseControlStatus, error) { var statusOperation *banzaiv1alpha1.CruiseControlOperation @@ -499,8 +534,8 @@ func (r *CruiseControlOperationReconciler) getStatus( // ignoring the error here to continue processing the operations, // even if the user does not provide a KafkaClusterRef label on the CCOperation then the ref will be an empty object (not nil) and the filter will skip it. ref, _ := kafkaClusterReference(ccOperation) - if ref.Name == kafkaCluster.Name && ref.Namespace == kafkaCluster.Namespace && - ccOperation.CurrentTaskOperation() == banzaiv1alpha1.OperationStatus && ccOperation.IsCurrentTaskRunning() { + if ref.Name == kafkaClusterRef.Name && ref.Namespace == kafkaClusterRef.Namespace && ccOperation.Status.CurrentTask != nil && + ccOperation.Status.CurrentTask.Operation == banzaiv1alpha1.OperationStatus && ccOperation.IsCurrentTaskRunning() { statusOperation = ccOperation break } diff --git a/controllers/cruisecontroloperation_controller_test.go b/controllers/cruisecontroloperation_controller_test.go index d7c0db642..1286bdf43 100644 --- a/controllers/cruisecontroloperation_controller_test.go +++ b/controllers/cruisecontroloperation_controller_test.go @@ -84,6 +84,21 @@ func TestSortOperations(t *testing.T) { createCCRetryExecutionOperation(timeNow, "3", v1alpha1.OperationRebalance), }, }, + { + testName: "mixed with remove disks", + ccOperations: []*v1alpha1.CruiseControlOperation{ + createCCRetryExecutionOperation(timeNow, "1", v1alpha1.OperationAddBroker), + createCCRetryExecutionOperation(timeNow, "4", v1alpha1.OperationRebalance), + createCCRetryExecutionOperation(timeNow.Add(2*time.Second), "3", v1alpha1.OperationRemoveDisks), + createCCRetryExecutionOperation(timeNow.Add(time.Second), "2", v1alpha1.OperationRemoveBroker), + }, + expectedOutput: []*v1alpha1.CruiseControlOperation{ + createCCRetryExecutionOperation(timeNow, "1", v1alpha1.OperationAddBroker), + createCCRetryExecutionOperation(timeNow.Add(time.Second), "2", v1alpha1.OperationRemoveBroker), + createCCRetryExecutionOperation(timeNow.Add(2*time.Second), "3", v1alpha1.OperationRemoveDisks), + createCCRetryExecutionOperation(timeNow, "4", v1alpha1.OperationRebalance), + }, + }, } for _, testCase := range testCases { sortedCCOperations := sortOperations(testCase.ccOperations) diff --git a/controllers/cruisecontroltask_controller.go b/controllers/cruisecontroltask_controller.go index ca823fbf7..2891bb19a 100644 --- a/controllers/cruisecontroltask_controller.go +++ b/controllers/cruisecontroltask_controller.go @@ -48,6 +48,7 @@ const ( DefaultRequeueAfterTimeInSec = 20 BrokerCapacityDisk = "DISK" BrokerCapacity = "capacity" + True = "true" ) // CruiseControlTaskReconciler reconciles a kafka cluster object @@ -62,6 +63,7 @@ type CruiseControlTaskReconciler struct { // +kubebuilder:rbac:groups=kafka.banzaicloud.io,resources=kafkaclusters/status,verbs=get;update;patch +//nolint:funlen,gocyclo func (r *CruiseControlTaskReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) { log := logr.FromContextOrDiscard(ctx) @@ -169,6 +171,55 @@ func (r *CruiseControlTaskReconciler) Reconcile(ctx context.Context, request ctr removeTask.SetCruiseControlOperationRef(cruiseControlOpRef) removeTask.SetStateScheduled() + case tasksAndStates.NumActiveTasksByOp(banzaiv1alpha1.OperationRemoveDisks) > 0: + brokerLogDirsToRemove := make(map[string][]string) + logDirsByBroker, err := scaler.LogDirsByBroker(ctx) + if err != nil { + return requeueWithError(log, "failed to get list of brokerIdsToLogDirs per broker from Cruise Control", err) + } + + for _, task := range tasksAndStates.GetActiveTasksByOp(banzaiv1alpha1.OperationRemoveDisks) { + if task == nil { + continue + } + + brokerID := task.BrokerID + volume := task.Volume + if _, ok := brokerLogDirsToRemove[brokerID]; !ok { + brokerLogDirsToRemove[brokerID] = []string{} + } + + found := false + if onlineDirs, ok := logDirsByBroker[brokerID][scale.LogDirStateOnline]; ok { + for _, dir := range onlineDirs { + if strings.HasPrefix(strings.TrimSpace(dir), strings.TrimSpace(volume)) { + brokerLogDirsToRemove[brokerID] = append(brokerLogDirsToRemove[brokerID], dir) + found = true + break + } + } + } + + if !found { + return requeueWithError(log, fmt.Sprintf("volume %s not found for broker %s in CC online log dirs", volume, brokerID), errors.New("log dir not found")) + } + } + + // create the cruise control operation + cruiseControlOpRef, err := r.removeDisks(ctx, instance, operationTTLSecondsAfterFinished, brokerLogDirsToRemove) + if err != nil { + return requeueWithError(log, fmt.Sprintf("creating CruiseControlOperation for disk removal has failed, brokerID and brokerIdsToLogDirs: %s", brokerLogDirsToRemove), err) + } + + for _, task := range tasksAndStates.GetActiveTasksByOp(banzaiv1alpha1.OperationRemoveDisks) { + if task == nil { + continue + } + + task.SetCruiseControlOperationRef(cruiseControlOpRef) + task.SetStateScheduled() + } + case tasksAndStates.NumActiveTasksByOp(banzaiv1alpha1.OperationRebalance) > 0: brokerIDs := make([]string, 0) for _, task := range tasksAndStates.GetActiveTasksByOp(banzaiv1alpha1.OperationRebalance) { @@ -280,25 +331,31 @@ func getUnavailableBrokers(ctx context.Context, scaler scale.CruiseControlScaler } func (r *CruiseControlTaskReconciler) addBrokers(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster, ttlSecondsAfterFinished *int, bokerIDs []string) (corev1.LocalObjectReference, error) { - return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationAddBroker, bokerIDs, false) + return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationAddBroker, bokerIDs, false, nil) } func (r *CruiseControlTaskReconciler) removeBroker(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster, ttlSecondsAfterFinished *int, brokerID string) (corev1.LocalObjectReference, error) { - return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationRemoveBroker, []string{brokerID}, false) + return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationRemoveBroker, []string{brokerID}, false, nil) +} + +func (r *CruiseControlTaskReconciler) removeDisks(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster, ttlSecondsAfterFinished *int, brokerIdsToRemovedLogDirs map[string][]string) (corev1.LocalObjectReference, error) { + return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationRemoveDisks, nil, false, brokerIdsToRemovedLogDirs) } func (r *CruiseControlTaskReconciler) rebalanceDisks(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster, ttlSecondsAfterFinished *int, bokerIDs []string, isJBOD bool) (corev1.LocalObjectReference, error) { - return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationRebalance, bokerIDs, isJBOD) + return r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, ttlSecondsAfterFinished, banzaiv1alpha1.OperationRebalance, bokerIDs, isJBOD, nil) } +//nolint:unparam func (r *CruiseControlTaskReconciler) createCCOperation( ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster, errorPolicy banzaiv1alpha1.ErrorPolicyType, ttlSecondsAfterFinished *int, operationType banzaiv1alpha1.CruiseControlTaskOperation, - bokerIDs []string, + brokerIDs []string, isJBOD bool, + logDirsByBrokerID map[string][]string, ) (corev1.LocalObjectReference, error) { operation := &banzaiv1alpha1.CruiseControlOperation{ ObjectMeta: metav1.ObjectMeta{ @@ -323,20 +380,32 @@ func (r *CruiseControlTaskReconciler) createCCOperation( } operation.Status.CurrentTask = &banzaiv1alpha1.CruiseControlTask{ - Operation: operationType, - Parameters: map[string]string{ - "exclude_recently_demoted_brokers": "true", - "exclude_recently_removed_brokers": "true", - }, + Operation: operationType, + Parameters: make(map[string]string), } - if operationType == banzaiv1alpha1.OperationRebalance { - operation.Status.CurrentTask.Parameters["destination_broker_ids"] = strings.Join(bokerIDs, ",") + if operationType != banzaiv1alpha1.OperationRemoveDisks { + operation.Status.CurrentTask.Parameters[scale.ParamExcludeDemoted] = True + operation.Status.CurrentTask.Parameters[scale.ParamExcludeRemoved] = True + } + + switch { + case operationType == banzaiv1alpha1.OperationRebalance: + operation.Status.CurrentTask.Parameters[scale.ParamDestbrokerIDs] = strings.Join(brokerIDs, ",") if isJBOD { - operation.Status.CurrentTask.Parameters["rebalance_disk"] = "true" + operation.Status.CurrentTask.Parameters[scale.ParamRebalanceDisk] = True } - } else { - operation.Status.CurrentTask.Parameters["brokerid"] = strings.Join(bokerIDs, ",") + case operationType == banzaiv1alpha1.OperationRemoveDisks: + pairs := make([]string, 0, len(logDirsByBrokerID)) + for brokerID, logDirs := range logDirsByBrokerID { + for _, logDir := range logDirs { + pair := fmt.Sprintf("%s-%s", brokerID, logDir) + pairs = append(pairs, pair) + } + } + operation.Status.CurrentTask.Parameters[scale.ParamBrokerIDAndLogDirs] = strings.Join(pairs, ",") + default: + operation.Status.CurrentTask.Parameters[scale.ParamBrokerID] = strings.Join(brokerIDs, ",") } if err := r.Status().Update(ctx, operation); err != nil { @@ -517,7 +586,8 @@ func getActiveTasksFromCluster(instance *banzaiv1beta1.KafkaCluster) *CruiseCont } for mountPath, volumeState := range brokerStatus.GracefulActionState.VolumeStates { - if volumeState.CruiseControlVolumeState.IsActive() { + switch { + case volumeState.CruiseControlVolumeState.IsDiskRebalance(): t := &CruiseControlTask{ BrokerID: brokerId, Volume: mountPath, @@ -526,6 +596,16 @@ func getActiveTasksFromCluster(instance *banzaiv1beta1.KafkaCluster) *CruiseCont CruiseControlOperationReference: volumeState.CruiseControlOperationReference, } tasksAndStates.Add(t) + + case volumeState.CruiseControlVolumeState.IsDiskRemoval(): + t := &CruiseControlTask{ + BrokerID: brokerId, + Volume: mountPath, + VolumeState: volumeState.CruiseControlVolumeState, + Operation: banzaiv1alpha1.OperationRemoveDisks, + CruiseControlOperationReference: volumeState.CruiseControlOperationReference, + } + tasksAndStates.Add(t) } } } diff --git a/controllers/cruisecontroltask_controller_test.go b/controllers/cruisecontroltask_controller_test.go index 5ff734e41..bc0f9f012 100644 --- a/controllers/cruisecontroltask_controller_test.go +++ b/controllers/cruisecontroltask_controller_test.go @@ -15,9 +15,21 @@ package controllers import ( + "context" "testing" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/banzaicloud/koperator/pkg/scale" + + banzaiv1alpha1 "github.com/banzaicloud/koperator/api/v1alpha1" + "github.com/banzaicloud/koperator/api/v1beta1" + "github.com/banzaicloud/koperator/pkg/resources/kafka/mocks" ) func TestBrokersJBODSelector(t *testing.T) { @@ -295,3 +307,111 @@ func TestBrokersJBODSelector(t *testing.T) { assert.ElementsMatch(t, testCase.expectedBrokersNotJBOD, brokersNotJBOD, "testName", testCase.testName) } } + +func TestCreateCCOperation(t *testing.T) { + t.Parallel() + ctx := context.Background() + ttlSecondsAfterFinished := 60 + + testCases := []struct { + operationType banzaiv1alpha1.CruiseControlTaskOperation + brokerIDs []string + isJBOD bool + brokerIdsToLogDirs map[string][]string + parameterCheck func(t *testing.T, params map[string]string) + }{ + { + operationType: banzaiv1alpha1.OperationAddBroker, + brokerIDs: []string{"1", "2", "3"}, + isJBOD: false, + brokerIdsToLogDirs: nil, + parameterCheck: func(t *testing.T, params map[string]string) { + assert.Equal(t, "1,2,3", params[scale.ParamBrokerID]) + assert.Equal(t, "true", params[scale.ParamExcludeDemoted]) + assert.Equal(t, "true", params[scale.ParamExcludeRemoved]) + }, + }, + { + operationType: banzaiv1alpha1.OperationRemoveBroker, + brokerIDs: []string{"1"}, + isJBOD: false, + brokerIdsToLogDirs: nil, + parameterCheck: func(t *testing.T, params map[string]string) { + assert.Equal(t, "1", params[scale.ParamBrokerID]) + assert.Equal(t, "true", params[scale.ParamExcludeDemoted]) + assert.Equal(t, "true", params[scale.ParamExcludeRemoved]) + }, + }, + { + operationType: banzaiv1alpha1.OperationRemoveDisks, + brokerIDs: []string{"1", "2"}, + isJBOD: false, + brokerIdsToLogDirs: map[string][]string{ + "1": {"logdir1", "logdir2"}, + "2": {"logdir1"}, + }, + parameterCheck: func(t *testing.T, params map[string]string) { + // can be in any order + expectedString1 := "1-logdir1,1-logdir2,2-logdir1" + expectedString2 := "2-logdir1,1-logdir1,1-logdir2" + assert.Contains(t, []string{expectedString1, expectedString2}, params[scale.ParamBrokerIDAndLogDirs]) + }, + }, + { + operationType: banzaiv1alpha1.OperationRebalance, + brokerIDs: []string{"1", "2", "3"}, + isJBOD: true, + brokerIdsToLogDirs: nil, + parameterCheck: func(t *testing.T, params map[string]string) { + assert.Equal(t, "1,2,3", params[scale.ParamDestbrokerIDs]) + assert.Equal(t, "true", params[scale.ParamRebalanceDisk]) + assert.Equal(t, "true", params[scale.ParamExcludeDemoted]) + assert.Equal(t, "true", params[scale.ParamExcludeRemoved]) + }, + }, + } + + mockCtrl := gomock.NewController(t) + + for _, testCase := range testCases { + mockClient := mocks.NewMockClient(mockCtrl) + mockSubResourceClient := mocks.NewMockSubResourceClient(mockCtrl) + scheme := runtime.NewScheme() + _ = v1beta1.AddToScheme(scheme) + _ = corev1.AddToScheme(scheme) + + r := CruiseControlTaskReconciler{ + Client: mockClient, + Scheme: scheme, + } + + kafkaCluster := &v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }} + + // Mock the Create call and capture the operation + var createdOperation *banzaiv1alpha1.CruiseControlOperation + mockClient.EXPECT().Create(ctx, gomock.AssignableToTypeOf(&banzaiv1alpha1.CruiseControlOperation{})).Do(func(ctx context.Context, obj client.Object, opts ...client.CreateOption) { + createdOperation = obj.(*banzaiv1alpha1.CruiseControlOperation) + createdOperation.ObjectMeta.Name = "generated-name" + }).Return(nil) + + // Mock the Status call + mockClient.EXPECT().Status().Return(mockSubResourceClient) + + // Mock the Update call + mockSubResourceClient.EXPECT().Update(ctx, gomock.AssignableToTypeOf(&banzaiv1alpha1.CruiseControlOperation{})).Do(func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) { + arg := obj.(*banzaiv1alpha1.CruiseControlOperation) + createdOperation.Status = arg.Status + }).Return(nil) + + _, err := r.createCCOperation(ctx, kafkaCluster, banzaiv1alpha1.ErrorPolicyRetry, &ttlSecondsAfterFinished, testCase.operationType, testCase.brokerIDs, testCase.isJBOD, testCase.brokerIdsToLogDirs) + assert.NoError(t, err) + + // Use the captured operation for further assertions + assert.Equal(t, testCase.operationType, createdOperation.Status.CurrentTask.Operation) + testCase.parameterCheck(t, createdOperation.Status.CurrentTask.Parameters) + } +} diff --git a/controllers/cruisecontroltask_types.go b/controllers/cruisecontroltask_types.go index ddbba3d08..c04f4af19 100644 --- a/controllers/cruisecontroltask_types.go +++ b/controllers/cruisecontroltask_types.go @@ -41,7 +41,7 @@ func (t *CruiseControlTask) IsRequired() bool { switch t.Operation { case koperatorv1alpha1.OperationAddBroker, koperatorv1alpha1.OperationRemoveBroker: return t.BrokerState.IsRequiredState() - case koperatorv1alpha1.OperationRebalance: + case koperatorv1alpha1.OperationRebalance, koperatorv1alpha1.OperationRemoveDisks: return t.VolumeState.IsRequiredState() } return false @@ -61,7 +61,7 @@ func (t *CruiseControlTask) Apply(instance *koperatorv1beta1.KafkaCluster) { state.GracefulActionState.CruiseControlOperationReference = t.CruiseControlOperationReference instance.Status.BrokersState[t.BrokerID] = state } - case koperatorv1alpha1.OperationRebalance: + case koperatorv1alpha1.OperationRebalance, koperatorv1alpha1.OperationRemoveDisks: if state, ok := instance.Status.BrokersState[t.BrokerID]; ok { if volState, ok := state.GracefulActionState.VolumeStates[t.Volume]; ok { volState.CruiseControlVolumeState = t.VolumeState @@ -88,10 +88,14 @@ func (t *CruiseControlTask) SetStateScheduled() { t.BrokerState = koperatorv1beta1.GracefulDownscaleScheduled case koperatorv1alpha1.OperationRebalance: t.VolumeState = koperatorv1beta1.GracefulDiskRebalanceScheduled + case koperatorv1alpha1.OperationRemoveDisks: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalScheduled } } // FromResult takes a scale.Result instance returned by scale.CruiseControlScaler and updates its own state accordingly. +// +//nolint:gocyclo func (t *CruiseControlTask) FromResult(operation *koperatorv1alpha1.CruiseControlOperation) { if t == nil { return @@ -135,6 +139,24 @@ func (t *CruiseControlTask) FromResult(operation *koperatorv1alpha1.CruiseContro t.BrokerState = koperatorv1beta1.GracefulDownscaleScheduled } + case koperatorv1alpha1.OperationRemoveDisks: + switch { + case operation == nil: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalSucceeded + case operation.IsErrorPolicyIgnore() && operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskCompletedWithError: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalSucceeded + case operation.IsPaused() && operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskCompletedWithError: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalPaused + case operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskActive, operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskInExecution: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalRunning + case operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskCompleted: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalSucceeded + case operation.CurrentTaskState() == koperatorv1beta1.CruiseControlTaskCompletedWithError: + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalCompletedWithError + case operation.CurrentTaskState() == "": + t.VolumeState = koperatorv1beta1.GracefulDiskRemovalScheduled + } + case koperatorv1alpha1.OperationRebalance: switch { case operation == nil: diff --git a/controllers/kafkacluster_controller.go b/controllers/kafkacluster_controller.go index 4043145d8..badf8f053 100644 --- a/controllers/kafkacluster_controller.go +++ b/controllers/kafkacluster_controller.go @@ -151,6 +151,7 @@ func (r *KafkaClusterReconciler) Reconcile(ctx context.Context, request ctrl.Req RequeueAfter: time.Duration(15) * time.Second, }, nil case errors.As(err, &errorfactory.CruiseControlTaskRunning{}): + log.Info("Cruise Control task running, requeuing", "error", err.Error()) return ctrl.Result{ RequeueAfter: time.Duration(20) * time.Second, }, nil diff --git a/controllers/kafkauser_controller.go b/controllers/kafkauser_controller.go index 35fc5b460..99cd5e89b 100644 --- a/controllers/kafkauser_controller.go +++ b/controllers/kafkauser_controller.go @@ -48,8 +48,6 @@ import ( "github.com/banzaicloud/koperator/pkg/util" kafkautil "github.com/banzaicloud/koperator/pkg/util/kafka" pkicommon "github.com/banzaicloud/koperator/pkg/util/pki" - - "sigs.k8s.io/controller-runtime/pkg/source" ) var userFinalizer = "finalizer.kafkausers.kafka.banzaicloud.io" @@ -67,7 +65,7 @@ func SetupKafkaUserWithManager(mgr ctrl.Manager, certSigningEnabled bool, certMa log: log, } builder.Watches( - &source.Kind{Type: &certsigningreqv1.CertificateSigningRequest{}}, + &certsigningreqv1.CertificateSigningRequest{}, handler.EnqueueRequestsFromMapFunc(csrMapper.mapToKafkaUser), ctrlBuilder.WithPredicates(certificateSigningRequestFilter(log))) } @@ -103,7 +101,7 @@ type csrMapper struct { } // mapToKafkaUser maps CertificateSigningRequest events to KafkaUser reconcile events -func (m *csrMapper) mapToKafkaUser(obj client.Object) []ctrl.Request { +func (m *csrMapper) mapToKafkaUser(ctx context.Context, obj client.Object) []ctrl.Request { certSigningReqAnnotations := obj.GetAnnotations() kafkaUserResourceNamespacedName, ok := certSigningReqAnnotations[pkicommon.KafkaUserAnnotationName] if !ok { @@ -117,7 +115,6 @@ func (m *csrMapper) mapToKafkaUser(obj client.Object) []ctrl.Request { namespace := namespaceWithName[0] name := namespaceWithName[1] - ctx := context.Background() var kafkaUser v1alpha1.KafkaUser err := m.client.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &kafkaUser) if err != nil { diff --git a/controllers/tests/clusterregistry/common_test.go b/controllers/tests/clusterregistry/common_test.go index 2487c6f22..cb680ded5 100644 --- a/controllers/tests/clusterregistry/common_test.go +++ b/controllers/tests/clusterregistry/common_test.go @@ -54,20 +54,20 @@ func createMinimalKafkaClusterCR(name, namespace string) *v1beta1.KafkaCluster { InternalListeners: []v1beta1.InternalListenerConfig{ { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "internal", - ContainerPort: 29092, + Type: "plaintext", + Name: "internal", + ContainerPort: 29092, + UsedForInnerBrokerCommunication: true, }, - UsedForInnerBrokerCommunication: true, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "controller", - ContainerPort: 29093, + Type: "plaintext", + Name: "controller", + ContainerPort: 29093, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, - UsedForControllerCommunication: true, + UsedForControllerCommunication: true, }, }, }, diff --git a/controllers/tests/clusterregistry/suite_test.go b/controllers/tests/clusterregistry/suite_test.go index 40b6bd34f..8a2e0a41d 100644 --- a/controllers/tests/clusterregistry/suite_test.go +++ b/controllers/tests/clusterregistry/suite_test.go @@ -49,6 +49,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" @@ -129,10 +131,14 @@ var _ = BeforeSuite(func() { Expect(k8sClient).NotTo(BeNil()) mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: "0", - LeaderElection: false, - Port: 8443, + Scheme: scheme, + LeaderElection: false, + Metrics: server.Options{ + BindAddress: "0", + }, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: 8443, + }), }) Expect(err).ToNot(HaveOccurred()) Expect(mgr).ToNot(BeNil()) diff --git a/controllers/tests/common_test.go b/controllers/tests/common_test.go index 15938c3e9..663ea3346 100644 --- a/controllers/tests/common_test.go +++ b/controllers/tests/common_test.go @@ -58,20 +58,20 @@ func createMinimalKafkaClusterCR(name, namespace string) *v1beta1.KafkaCluster { InternalListeners: []v1beta1.InternalListenerConfig{ { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "internal", - ContainerPort: 29092, + Type: "plaintext", + Name: "internal", + ContainerPort: 29092, + UsedForInnerBrokerCommunication: true, }, - UsedForInnerBrokerCommunication: true, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "controller", - ContainerPort: 29093, + Type: "plaintext", + Name: "controller", + ContainerPort: 29093, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, - UsedForControllerCommunication: true, + UsedForControllerCommunication: true, }, }, }, @@ -124,7 +124,7 @@ func createMinimalKafkaClusterCR(name, namespace string) *v1beta1.KafkaCluster { CCJMXExporterConfig: "custom_property: custom_value", }, ReadOnlyConfig: "cruise.control.metrics.topic.auto.create=true", - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{FailureThreshold: 1, ConcurrentBrokerRestartCountPerRack: 1}, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{FailureThreshold: 1, ConcurrentBrokerRestartsAllowed: 1}, }, } } @@ -160,7 +160,7 @@ func waitForClusterRunningState(ctx context.Context, kafkaCluster *v1beta1.Kafka } }() - Eventually(ch, 120*time.Second, 50*time.Millisecond).Should(Receive()) + Eventually(ch, 240*time.Second, 50*time.Millisecond).Should(Receive()) } func getMockedKafkaClientForCluster(kafkaCluster *v1beta1.KafkaCluster) (kafkaclient.KafkaClient, func()) { diff --git a/controllers/tests/cruisecontroloperation_controller_test.go b/controllers/tests/cruisecontroloperation_controller_test.go index 67059a505..ba1b1c823 100644 --- a/controllers/tests/cruisecontroloperation_controller_test.go +++ b/controllers/tests/cruisecontroloperation_controller_test.go @@ -305,6 +305,60 @@ var _ = Describe("CruiseControlTaskReconciler", func() { }, 10*time.Second, 500*time.Millisecond).Should(BeTrue()) }) }) + When("there is an errored remove_disks and a rebalance disks operation for the same broker", Serial, func() { + JustBeforeEach(func() { + cruiseControlOperationReconciler.ScaleFactory = mocks.NewMockScaleFactory(getScaleMock6()) + // Remove_disk operation - errored + operation := generateCruiseControlOperation(opName1, namespace, kafkaCluster.GetName()) + err := k8sClient.Create(context.Background(), &operation) + Expect(err).NotTo(HaveOccurred()) + + operation.Status.CurrentTask = &v1alpha1.CruiseControlTask{ + Operation: v1alpha1.OperationRemoveDisks, + Finished: &metav1.Time{Time: time.Now().Add(-time.Second*v1alpha1.DefaultRetryBackOffDurationSec - 10)}, + Parameters: map[string]string{ + scale.ParamBrokerIDAndLogDirs: "101-logdir1", + }, + } + err = k8sClient.Status().Update(context.Background(), &operation) + Expect(err).NotTo(HaveOccurred()) + // Rebalance operation + operation = generateCruiseControlOperation(opName2, namespace, kafkaCluster.GetName()) + err = k8sClient.Create(context.Background(), &operation) + Expect(err).NotTo(HaveOccurred()) + operation.Status.CurrentTask = &v1alpha1.CruiseControlTask{ + Operation: v1alpha1.OperationRebalance, + Parameters: map[string]string{ + scale.ParamDestbrokerIDs: "101,102", + }, + } + err = k8sClient.Status().Update(context.Background(), &operation) + Expect(err).NotTo(HaveOccurred()) + }) + It("should mark the removed disk task as paused and should execute the rebalance", func() { + Eventually(func() bool { + removeDisksOp := v1alpha1.CruiseControlOperation{} + err := k8sClient.Get(context.Background(), client.ObjectKey{ + Namespace: kafkaCluster.Namespace, + Name: opName1, + }, &removeDisksOp) + if err != nil { + return false + } + rebalanceOp := v1alpha1.CruiseControlOperation{} + err = k8sClient.Get(context.Background(), client.ObjectKey{ + Namespace: kafkaCluster.Namespace, + Name: opName2, + }, &rebalanceOp) + if err != nil { + return false + } + + return rebalanceOp.CurrentTaskState() == v1beta1.CruiseControlTaskCompleted && + removeDisksOp.GetLabels()[v1alpha1.PauseLabel] == v1alpha1.True + }, 10*time.Second, 500*time.Millisecond).Should(BeTrue()) + }) + }) When("Cruise Control makes the Status operation async", Serial, func() { JustBeforeEach(func(ctx SpecContext) { cruiseControlOperationReconciler.ScaleFactory = mocks.NewMockScaleFactory(getScaleMock7()) @@ -489,6 +543,38 @@ func getScaleMock5() *mocks.MockCruiseControlScaler { return scaleMock } +func getScaleMock6() *mocks.MockCruiseControlScaler { + mockCtrl := gomock.NewController(GinkgoT()) + scaleMock := mocks.NewMockCruiseControlScaler(mockCtrl) + scaleMock.EXPECT().IsUp(gomock.Any()).Return(true).AnyTimes() + + userTaskResult := []*scale.Result{scaleResultPointer(scale.Result{ + TaskID: "12345", + StartedAt: "Sat, 27 Aug 2022 12:22:21 GMT", + State: v1beta1.CruiseControlTaskCompletedWithError, + })} + scaleMock.EXPECT().UserTasks(gomock.Any(), gomock.Any()).Return(userTaskResult, nil).AnyTimes() + scaleMock.EXPECT().Status(gomock.Any()).Return(scale.StatusTaskResult{ + Status: &scale.CruiseControlStatus{ + ExecutorReady: true, + MonitorReady: true, + AnalyzerReady: true, + }}, nil).AnyTimes() + scaleMock.EXPECT().RebalanceWithParams(gomock.Any(), gomock.All()).Return(scaleResultPointer(scale.Result{ + TaskID: "12346", + StartedAt: "Sat, 27 Aug 2022 12:22:21 GMT", + State: v1beta1.CruiseControlTaskCompleted, + }), nil).Times(1) + + scaleMock.EXPECT().RemoveDisksWithParams(gomock.Any(), gomock.All()).Return(scaleResultPointer(scale.Result{ + TaskID: "12345", + StartedAt: "Sat, 27 Aug 2022 12:22:21 GMT", + State: v1beta1.CruiseControlTaskCompletedWithError, + }), nil).AnyTimes() + + return scaleMock +} + func getScaleMock7() *mocks.MockCruiseControlScaler { mockCtrl := gomock.NewController(GinkgoT()) scaleMock := mocks.NewMockCruiseControlScaler(mockCtrl) diff --git a/controllers/tests/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 7a7d7ae78..60176badb 100644 --- a/controllers/tests/kafkacluster_controller_envoy_test.go +++ b/controllers/tests/kafkacluster_controller_envoy_test.go @@ -120,6 +120,11 @@ staticResources: portValue: 9094 name: broker-0 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -143,6 +148,11 @@ staticResources: portValue: 9094 name: broker-1 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -166,6 +176,11 @@ staticResources: portValue: 9094 name: broker-2 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -203,6 +218,11 @@ staticResources: portValue: 9020 name: all-brokers type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 listeners: - address: socketAddress: @@ -214,8 +234,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-0 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-0 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -226,8 +260,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-1 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-1 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -238,8 +286,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-2 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-2 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -250,8 +312,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: all-brokers + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: all-brokers + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -273,8 +349,10 @@ staticResources: all-brokers: value: 1 headers: - - exactMatch: /healthcheck - name: :path + - name: :path + stringMatch: + exact: /healthcheck + ignoreCase: true passThroughMode: false - name: envoy.filters.http.router typedConfig: @@ -291,6 +369,19 @@ staticResources: redirect: pathRedirect: /healthcheck statPrefix: all-brokers-healthcheck + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" `, fmt.Sprintf(svcTemplate, "0"), fmt.Sprintf(svcTemplate, "1"), fmt.Sprintf(svcTemplate, "2"), fmt.Sprintf(svcTemplate, "all-broker")) Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) } @@ -473,6 +564,11 @@ staticResources: portValue: 9094 name: broker-0 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -510,6 +606,11 @@ staticResources: portValue: 9020 name: all-brokers type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 listeners: - address: socketAddress: @@ -521,8 +622,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-0 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-0 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -533,8 +648,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: all-brokers + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: all-brokers + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -556,8 +685,10 @@ staticResources: all-brokers: value: 1 headers: - - exactMatch: /healthcheck - name: :path + - name: :path + stringMatch: + exact: /healthcheck + ignoreCase: true passThroughMode: false - name: envoy.filters.http.router typedConfig: @@ -576,6 +707,286 @@ staticResources: redirect: pathRedirect: /healthcheck statPrefix: all-brokers-healthcheck + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" +`, fmt.Sprintf(svcTemplate, "0"), fmt.Sprintf(svcTemplate, "all-broker")) + Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) +} + +func expectEnvoyWithConfigAz1Tls(kafkaCluster *v1beta1.KafkaCluster) { + var loadBalancer corev1.Service + lbName := fmt.Sprintf("envoy-loadbalancer-test-az1-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: lbName}, &loadBalancer) + return err + }).Should(Succeed()) + Expect(loadBalancer.Spec.Ports).To(HaveLen(3)) + + Expect(loadBalancer.Spec.Ports[0].Name).To(Equal("tcp-all-broker")) + Expect(loadBalancer.Spec.Ports[0].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[0].Port).To(BeEquivalentTo(29092)) + Expect(loadBalancer.Spec.Ports[0].TargetPort.StrVal).To(BeEquivalentTo("tcp-all-broker")) + + Expect(loadBalancer.Spec.Ports[1].Name).To(Equal("tcp-health")) + Expect(loadBalancer.Spec.Ports[1].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[1].Port).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort())) + Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort())) + + Expect(loadBalancer.Spec.Ports[2].Name).To(Equal("tcp-admin")) + Expect(loadBalancer.Spec.Ports[2].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[2].Port).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort())) + Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort())) + + var deployment appsv1.Deployment + deploymentName := fmt.Sprintf("envoy-test-az1-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: deploymentName}, &deployment) + return err + }).Should(Succeed()) + templateSpec := deployment.Spec.Template.Spec + Expect(templateSpec.Containers).To(HaveLen(1)) + container := templateSpec.Containers[0] + Expect(container.Ports).To(ConsistOf( + corev1.ContainerPort{ + Name: "tcp-all-broker", + ContainerPort: 29092, + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-admin", + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-health", + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort(), + Protocol: corev1.ProtocolTCP, + }, + )) + + var configMap corev1.ConfigMap + configMapName := fmt.Sprintf("envoy-config-test-az1-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: configMapName}, &configMap) + return err + }).Should(Succeed()) + Expect(configMap.Data).To(HaveKey("envoy.yaml")) + svcTemplate := fmt.Sprintf("%s-%s.%s.svc.%s", kafkaCluster.Name, "%s", kafkaCluster.Namespace, kafkaCluster.Spec.GetKubernetesClusterDomain()) + expected := fmt.Sprintf(`admin: + address: + socketAddress: + address: 0.0.0.0 + portValue: 8081 +staticResources: + clusters: + - circuitBreakers: + thresholds: + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + priority: HIGH + connectTimeout: 1s + loadAssignment: + clusterName: broker-0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: %s + portValue: 9094 + name: broker-0 + type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 + - circuitBreakers: + thresholds: + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + priority: HIGH + connectTimeout: 1s + healthChecks: + - eventLogPath: /dev/stdout + healthyThreshold: 1 + httpHealthCheck: + path: /-/healthy + interval: 5s + intervalJitter: 1s + noTrafficInterval: 5s + timeout: 1s + unhealthyInterval: 2s + unhealthyThreshold: 2 + ignoreHealthOnHostRemoval: true + loadAssignment: + clusterName: all-brokers + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: %s + portValue: 9094 + healthCheckConfig: + portValue: 9020 + name: all-brokers + type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 + listeners: + - address: + socketAddress: + address: 0.0.0.0 + portValue: 29092 + filterChains: + - filterChainMatch: + serverNames: + - broker-0 + transportProtocol: tls + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: broker-0 + idleTimeout: 560s + maxConnectAttempts: 2 + statPrefix: broker_tcp-0 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/certificate.crt + privateKey: + filename: /certs/private.key + tlsParams: + tlsMaximumProtocolVersion: TLSv1_3 + tlsMinimumProtocolVersion: TLSv1_2 + - filterChainMatch: + serverNames: + - all-brokers-az1 + transportProtocol: tls + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: all-brokers + idleTimeout: 560s + maxConnectAttempts: 2 + statPrefix: all-brokers + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/certificate.crt + privateKey: + filename: /certs/private.key + tlsParams: + tlsMaximumProtocolVersion: TLSv1_3 + tlsMinimumProtocolVersion: TLSv1_2 + listenerFilters: + - name: tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" + - address: + socketAddress: + address: 0.0.0.0 + portValue: 8080 + filterChains: + - filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + accessLog: + - name: envoy.access_loggers.stdout + typedConfig: + '@type': type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + httpFilters: + - name: envoy.filters.http.health_check + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + clusterMinHealthyPercentages: + all-brokers: + value: 1 + headers: + - name: :path + stringMatch: + exact: /healthcheck + ignoreCase: true + passThroughMode: false + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + routeConfig: + name: local + virtualHosts: + - domains: + - '*' + name: localhost + routes: + - match: + prefix: / + redirect: + pathRedirect: /healthcheck + statPrefix: all-brokers-healthcheck + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" `, fmt.Sprintf(svcTemplate, "0"), fmt.Sprintf(svcTemplate, "all-broker")) Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) } @@ -688,6 +1099,11 @@ staticResources: portValue: 9094 name: broker-1 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -711,6 +1127,11 @@ staticResources: portValue: 9094 name: broker-2 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -748,6 +1169,11 @@ staticResources: portValue: 9020 name: all-brokers type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 listeners: - address: socketAddress: @@ -759,8 +1185,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-1 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-1 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -771,8 +1211,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: broker-2 + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: broker_tcp-2 + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -783,8 +1237,22 @@ staticResources: typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy cluster: all-brokers + idleTimeout: 560s maxConnectAttempts: 2 statPrefix: all-brokers + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" - address: socketAddress: address: 0.0.0.0 @@ -806,8 +1274,10 @@ staticResources: all-brokers: value: 1 headers: - - exactMatch: /healthcheck - name: :path + - name: :path + stringMatch: + exact: /healthcheck + ignoreCase: true passThroughMode: false - name: envoy.filters.http.router typedConfig: @@ -826,6 +1296,339 @@ staticResources: redirect: pathRedirect: /healthcheck statPrefix: all-brokers-healthcheck + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" +`, fmt.Sprintf(svcTemplate, "1"), fmt.Sprintf(svcTemplate, "2"), fmt.Sprintf(svcTemplate, "all-broker")) + Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) +} + +func expectEnvoyWithConfigAz2Tls(kafkaCluster *v1beta1.KafkaCluster) { + var loadBalancer corev1.Service + lbName := fmt.Sprintf("envoy-loadbalancer-test-az2-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: lbName}, &loadBalancer) + return err + }).Should(Succeed()) + Expect(loadBalancer.Spec.Ports).To(HaveLen(3)) + + Expect(loadBalancer.Spec.Ports[0].Name).To(Equal("tcp-all-broker")) + Expect(loadBalancer.Spec.Ports[0].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[0].Port).To(BeEquivalentTo(29092)) + Expect(loadBalancer.Spec.Ports[0].TargetPort.StrVal).To(BeEquivalentTo("tcp-all-broker")) + + Expect(loadBalancer.Spec.Ports[1].Name).To(Equal("tcp-health")) + Expect(loadBalancer.Spec.Ports[1].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[1].Port).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort())) + Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort())) + + Expect(loadBalancer.Spec.Ports[2].Name).To(Equal("tcp-admin")) + Expect(loadBalancer.Spec.Ports[2].Protocol).To(Equal(corev1.ProtocolTCP)) + Expect(loadBalancer.Spec.Ports[2].Port).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort())) + Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort())) + + var deployment appsv1.Deployment + deploymentName := fmt.Sprintf("envoy-test-az2-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: deploymentName}, &deployment) + return err + }).Should(Succeed()) + templateSpec := deployment.Spec.Template.Spec + Expect(templateSpec.Containers).To(HaveLen(1)) + container := templateSpec.Containers[0] + Expect(container.Ports).To(ConsistOf( + corev1.ContainerPort{ + Name: "tcp-all-broker", + ContainerPort: 29092, + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-admin", + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-health", + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort(), + Protocol: corev1.ProtocolTCP, + }, + )) + + var configMap corev1.ConfigMap + configMapName := fmt.Sprintf("envoy-config-test-az2-%s", kafkaCluster.Name) + Eventually(func() error { + err := k8sClient.Get(context.Background(), types.NamespacedName{Namespace: kafkaCluster.Namespace, Name: configMapName}, &configMap) + return err + }).Should(Succeed()) + Expect(configMap.Data).To(HaveKey("envoy.yaml")) + svcTemplate := fmt.Sprintf("%s-%s.%s.svc.%s", kafkaCluster.Name, "%s", kafkaCluster.Namespace, kafkaCluster.Spec.GetKubernetesClusterDomain()) + expected := fmt.Sprintf(`admin: + address: + socketAddress: + address: 0.0.0.0 + portValue: 8081 +staticResources: + clusters: + - circuitBreakers: + thresholds: + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + priority: HIGH + connectTimeout: 1s + loadAssignment: + clusterName: broker-1 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: %s + portValue: 9094 + name: broker-1 + type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 + - circuitBreakers: + thresholds: + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + priority: HIGH + connectTimeout: 1s + loadAssignment: + clusterName: broker-2 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: %s + portValue: 9094 + name: broker-2 + type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 + - circuitBreakers: + thresholds: + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + - maxConnections: 1000000000 + maxPendingRequests: 1000000000 + maxRequests: 1000000000 + maxRetries: 1000000000 + priority: HIGH + connectTimeout: 1s + healthChecks: + - eventLogPath: /dev/stdout + healthyThreshold: 1 + httpHealthCheck: + path: /-/healthy + interval: 5s + intervalJitter: 1s + noTrafficInterval: 5s + timeout: 1s + unhealthyInterval: 2s + unhealthyThreshold: 2 + ignoreHealthOnHostRemoval: true + loadAssignment: + clusterName: all-brokers + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: %s + portValue: 9094 + healthCheckConfig: + portValue: 9020 + name: all-brokers + type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 + listeners: + - address: + socketAddress: + address: 0.0.0.0 + portValue: 29092 + filterChains: + - filterChainMatch: + serverNames: + - broker-1 + transportProtocol: tls + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: broker-1 + idleTimeout: 560s + maxConnectAttempts: 2 + statPrefix: broker_tcp-1 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/certificate.crt + privateKey: + filename: /certs/private.key + tlsParams: + tlsMaximumProtocolVersion: TLSv1_3 + tlsMinimumProtocolVersion: TLSv1_2 + - filterChainMatch: + serverNames: + - broker-2 + transportProtocol: tls + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: broker-2 + idleTimeout: 560s + maxConnectAttempts: 2 + statPrefix: broker_tcp-2 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/certificate.crt + privateKey: + filename: /certs/private.key + tlsParams: + tlsMaximumProtocolVersion: TLSv1_3 + tlsMinimumProtocolVersion: TLSv1_2 + - filterChainMatch: + serverNames: + - all-brokers-az2 + transportProtocol: tls + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: all-brokers + idleTimeout: 560s + maxConnectAttempts: 2 + statPrefix: all-brokers + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + tlsCertificates: + - certificateChain: + filename: /certs/certificate.crt + privateKey: + filename: /certs/private.key + tlsParams: + tlsMaximumProtocolVersion: TLSv1_3 + tlsMinimumProtocolVersion: TLSv1_2 + listenerFilters: + - name: tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" + - address: + socketAddress: + address: 0.0.0.0 + portValue: 8080 + filterChains: + - filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + accessLog: + - name: envoy.access_loggers.stdout + typedConfig: + '@type': type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + httpFilters: + - name: envoy.filters.http.health_check + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + clusterMinHealthyPercentages: + all-brokers: + value: 1 + headers: + - name: :path + stringMatch: + exact: /healthcheck + ignoreCase: true + passThroughMode: false + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + routeConfig: + name: local + virtualHosts: + - domains: + - '*' + name: localhost + routes: + - match: + prefix: / + redirect: + pathRedirect: /healthcheck + statPrefix: all-brokers-healthcheck + socketOptions: + - intValue: "1" + level: "1" + name: "9" + - intValue: "30" + level: "6" + name: "4" + - intValue: "30" + level: "6" + name: "5" + - intValue: "3" + level: "6" + name: "6" `, fmt.Sprintf(svcTemplate, "1"), fmt.Sprintf(svcTemplate, "2"), fmt.Sprintf(svcTemplate, "all-broker")) Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) } diff --git a/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go b/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go index 8778db1b0..9b7cbeecf 100644 --- a/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go +++ b/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go @@ -50,14 +50,14 @@ func expectDefaultBrokerSettingsForExternalListenerBinding(ctx context.Context, Expect(err).NotTo(HaveOccurred()) advertisedListener, found := brokerConfig.Get("advertised.listeners") Expect(found).To(BeTrue()) - Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("CONTROLLER://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29092,TEST://external.az1.host.com:%d", - randomGenTestNumber, broker.Id, randomGenTestNumber, randomGenTestNumber, broker.Id, randomGenTestNumber, 19090+broker.Id))) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://external.az1.host.com:%d,CONTROLLER://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29092", + 19090+broker.Id, randomGenTestNumber, broker.Id, randomGenTestNumber, randomGenTestNumber, broker.Id, randomGenTestNumber))) listeners, found := brokerConfig.Get("listeners") Expect(found).To(BeTrue()) - Expect(listeners.Value()).To(Equal("INTERNAL://:29092,CONTROLLER://:29093,TEST://:9094")) + Expect(listeners.Value()).To(Equal("TEST://:9094,INTERNAL://:29092,CONTROLLER://:29093")) listenerSecMap, found := brokerConfig.Get(kafkautils.KafkaConfigListenerSecurityProtocolMap) Expect(found).To(BeTrue()) - Expect(listenerSecMap.Value()).To(Equal("INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,TEST:PLAINTEXT")) + Expect(listenerSecMap.Value()).To(Equal("TEST:PLAINTEXT,INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT")) // check service service := corev1.Service{} Eventually(ctx, func() error { @@ -112,8 +112,25 @@ func expectBrokerConfigmapForAz1ExternalListener(ctx context.Context, kafkaClust Expect(err).NotTo(HaveOccurred()) advertisedListener, found := brokerConfig.Get("advertised.listeners") Expect(found).To(BeTrue()) - Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092,TEST://external.az1.host.com:%d", - randomGenTestNumber, 0, randomGenTestNumber, randomGenTestNumber, 0, randomGenTestNumber, 19090))) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://external.az1.host.com:%d,CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092", + 19090, randomGenTestNumber, 0, randomGenTestNumber, randomGenTestNumber, 0, randomGenTestNumber))) +} + +func expectBrokerConfigmapForAz1ExternalListenerTls(kafkaCluster *v1beta1.KafkaCluster, randomGenTestNumber uint64) { + configMap := corev1.ConfigMap{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{ + Namespace: kafkaCluster.Namespace, + Name: fmt.Sprintf("%s-config-%d", kafkaCluster.Name, 0), + }, &configMap) + }).Should(Succeed()) + + brokerConfig, err := properties.NewFromString(configMap.Data["broker-config"]) + Expect(err).NotTo(HaveOccurred()) + advertisedListener, found := brokerConfig.Get("advertised.listeners") + Expect(found).To(BeTrue()) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://broker-0:%d,CONTROLLER://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29092", + 29092, randomGenTestNumber, 0, randomGenTestNumber, randomGenTestNumber, 0, randomGenTestNumber))) } func expectBrokerConfigmapForAz2ExternalListener(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster, randomGenTestNumber uint64) { @@ -129,8 +146,8 @@ func expectBrokerConfigmapForAz2ExternalListener(ctx context.Context, kafkaClust Expect(err).NotTo(HaveOccurred()) advertisedListener, found := brokerConfig.Get("advertised.listeners") Expect(found).To(BeTrue()) - Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092,TEST://external.az2.host.com:%d", - randomGenTestNumber, 1, randomGenTestNumber, randomGenTestNumber, 1, randomGenTestNumber, 19091))) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://external.az2.host.com:%d,CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092", + 19091, randomGenTestNumber, 1, randomGenTestNumber, randomGenTestNumber, 1, randomGenTestNumber))) configMap = corev1.ConfigMap{} Eventually(ctx, func() error { @@ -144,6 +161,38 @@ func expectBrokerConfigmapForAz2ExternalListener(ctx context.Context, kafkaClust Expect(err).NotTo(HaveOccurred()) advertisedListener, found = brokerConfig.Get("advertised.listeners") Expect(found).To(BeTrue()) - Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092,TEST://external.az2.host.com:%d", - randomGenTestNumber, 2, randomGenTestNumber, randomGenTestNumber, 2, randomGenTestNumber, 19092))) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://external.az2.host.com:%d,CONTROLLER://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafkaconfigtest-%d.svc.cluster.local:29092", + 19092, randomGenTestNumber, 2, randomGenTestNumber, randomGenTestNumber, 2, randomGenTestNumber))) +} + +func expectBrokerConfigmapForAz2ExternalListenerTls(kafkaCluster *v1beta1.KafkaCluster, randomGenTestNumber uint64) { + configMap := corev1.ConfigMap{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{ + Namespace: kafkaCluster.Namespace, + Name: fmt.Sprintf("%s-config-%d", kafkaCluster.Name, 1), + }, &configMap) + }).Should(Succeed()) + + brokerConfig, err := properties.NewFromString(configMap.Data["broker-config"]) + Expect(err).NotTo(HaveOccurred()) + advertisedListener, found := brokerConfig.Get("advertised.listeners") + Expect(found).To(BeTrue()) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://broker-1:%d,CONTROLLER://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29092", + 29092, randomGenTestNumber, 1, randomGenTestNumber, randomGenTestNumber, 1, randomGenTestNumber))) + + configMap = corev1.ConfigMap{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{ + Namespace: kafkaCluster.Namespace, + Name: fmt.Sprintf("%s-config-%d", kafkaCluster.Name, 2), + }, &configMap) + }).Should(Succeed()) + + brokerConfig, err = properties.NewFromString(configMap.Data["broker-config"]) + Expect(err).NotTo(HaveOccurred()) + advertisedListener, found = brokerConfig.Get("advertised.listeners") + Expect(found).To(BeTrue()) + Expect(advertisedListener.Value()).To(Equal(fmt.Sprintf("TEST://broker-2:%d,CONTROLLER://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29093,INTERNAL://kafkaclustertls-%d-%d.kafkatlsconfigtest-%d.svc.cluster.local:29092", + 29092, randomGenTestNumber, 2, randomGenTestNumber, randomGenTestNumber, 2, randomGenTestNumber))) } diff --git a/controllers/tests/kafkacluster_controller_externalnodeport_test.go b/controllers/tests/kafkacluster_controller_externalnodeport_test.go index 9b7372e61..be9ad4229 100644 --- a/controllers/tests/kafkacluster_controller_externalnodeport_test.go +++ b/controllers/tests/kafkacluster_controller_externalnodeport_test.go @@ -28,6 +28,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/banzaicloud/koperator/api/v1beta1" ) @@ -91,6 +92,8 @@ var _ = Describe("KafkaClusterNodeportExternalAccess", func() { By("deleting Kafka cluster object " + kafkaCluster.Name + " in namespace " + namespace) err := k8sClient.Delete(ctx, kafkaCluster) Expect(err).NotTo(HaveOccurred()) + // deletes all nodeports in the test namespace, to ensure a clean sheet, as garbage collection does not work in envtest + Expect(deleteNodePorts(ctx, kafkaCluster)).Should(Succeed()) kafkaCluster = nil }) @@ -236,7 +239,7 @@ var _ = Describe("KafkaClusterNodeportExternalAccess", func() { ContainerPort: 9733, Type: "plaintext", }, - ExternalStartingPort: 30300, + ExternalStartingPort: 30410, IngressServiceSettings: v1beta1.IngressServiceSettings{ HostnameOverride: ".external.nodeport.com", }, @@ -277,15 +280,15 @@ var _ = Describe("KafkaClusterNodeportExternalAccess", func() { "test": { { Name: "broker-0", - Address: fmt.Sprintf("%s-0-test.kafka-nodeport-%d.external.nodeport.com:30300", kafkaCluster.Name, count), + Address: fmt.Sprintf("%s-0-test.kafka-nodeport-%d.external.nodeport.com:30410", kafkaCluster.Name, count), }, { Name: "broker-1", - Address: fmt.Sprintf("%s-1-test.kafka-nodeport-%d.external.nodeport.com:30301", kafkaCluster.Name, count), + Address: fmt.Sprintf("%s-1-test.kafka-nodeport-%d.external.nodeport.com:30411", kafkaCluster.Name, count), }, { Name: "broker-2", - Address: fmt.Sprintf("%s-2-test.kafka-nodeport-%d.external.nodeport.com:30302", kafkaCluster.Name, count), + Address: fmt.Sprintf("%s-2-test.kafka-nodeport-%d.external.nodeport.com:30412", kafkaCluster.Name, count), }, }, }, @@ -370,3 +373,20 @@ var _ = Describe("KafkaClusterNodeportExternalAccess", func() { }) }) }) + +func deleteNodePorts(ctx SpecContext, kafkaCluster *v1beta1.KafkaCluster) error { + var serviceList corev1.ServiceList + err := k8sClient.List(ctx, &serviceList, client.ListOption(client.InNamespace(kafkaCluster.Namespace))) + if err != nil { + return err + } + for _, service := range serviceList.Items { + if service.Spec.Type == corev1.ServiceTypeNodePort { + err = k8sClient.Delete(ctx, &service) + if err != nil { + return err + } + } + } + return nil +} diff --git a/controllers/tests/kafkacluster_controller_kafka_test.go b/controllers/tests/kafkacluster_controller_kafka_test.go index 5d74b2734..48ebcf4c3 100644 --- a/controllers/tests/kafkacluster_controller_kafka_test.go +++ b/controllers/tests/kafkacluster_controller_kafka_test.go @@ -162,18 +162,18 @@ func expectKafkaBrokerConfigmap(ctx context.Context, kafkaCluster *v1beta1.Kafka Expect(configMap.Labels).To(HaveKeyWithValue(v1beta1.KafkaCRLabelKey, kafkaCluster.Name)) Expect(configMap.Labels).To(HaveKeyWithValue(v1beta1.BrokerIdLabelKey, strconv.Itoa(int(broker.Id)))) - Expect(configMap.Data).To(HaveKeyWithValue("broker-config", fmt.Sprintf(`advertised.listeners=CONTROLLER://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29092,TEST://test.host.com:%d + Expect(configMap.Data).To(HaveKeyWithValue("broker-config", fmt.Sprintf(`advertised.listeners=TEST://test.host.com:%d,CONTROLLER://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29093,INTERNAL://kafkacluster-%d-%d.kafka-%d.svc.cluster.local:29092 broker.id=%d control.plane.listener.name=CONTROLLER cruise.control.metrics.reporter.bootstrap.servers=kafkacluster-1-all-broker.kafka-1.svc.cluster.local:29092 cruise.control.metrics.reporter.kubernetes.mode=true inter.broker.listener.name=INTERNAL -listener.security.protocol.map=INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,TEST:PLAINTEXT -listeners=INTERNAL://:29092,CONTROLLER://:29093,TEST://:9094 +listener.security.protocol.map=TEST:PLAINTEXT,INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT +listeners=TEST://:9094,INTERNAL://:29092,CONTROLLER://:29093 log.dirs=/kafka-logs/kafka,/ephemeral-dir1/kafka metric.reporters=com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter zookeeper.connect=/ -`, randomGenTestNumber, broker.Id, randomGenTestNumber, randomGenTestNumber, broker.Id, randomGenTestNumber, 19090+broker.Id, broker.Id))) +`, 19090+broker.Id, randomGenTestNumber, broker.Id, randomGenTestNumber, randomGenTestNumber, broker.Id, randomGenTestNumber, broker.Id))) // assert log4j? } diff --git a/controllers/tests/kafkacluster_controller_test.go b/controllers/tests/kafkacluster_controller_test.go index 3a68c5b06..f066cc63c 100644 --- a/controllers/tests/kafkacluster_controller_test.go +++ b/controllers/tests/kafkacluster_controller_test.go @@ -380,6 +380,80 @@ var _ = Describe("KafkaCluster with two config external listener", func() { }) }) +var _ = Describe("KafkaCluster with two config external listener and tls", func() { + var ( + count uint64 = 0 + namespace string + namespaceObj *corev1.Namespace + kafkaCluster *v1beta1.KafkaCluster + ) + + BeforeEach(func() { + atomic.AddUint64(&count, 1) + + namespace = fmt.Sprintf("kafkatlsconfigtest-%v", count) + namespaceObj = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + + kafkaCluster = createMinimalKafkaClusterCR(fmt.Sprintf("kafkaclustertls-%d", count), namespace) + kafkaCluster.Spec.ListenersConfig.ExternalListeners[0].HostnameOverride = "" + testExternalListener := kafkaCluster.Spec.ListenersConfig.ExternalListeners[0] + testExternalListener.ExternalStartingPort = -1 + testExternalListener.TLSSecretName = "tls-secret" + testExternalListener.Config = &v1beta1.Config{ + DefaultIngressConfig: "az2", + IngressConfig: map[string]v1beta1.IngressConfig{ + "az1": { + EnvoyConfig: &v1beta1.EnvoyConfig{ + Annotations: map[string]string{"zone": "az1"}, + BrokerHostnameTemplate: "broker-%id", + }, + IngressServiceSettings: v1beta1.IngressServiceSettings{ + HostnameOverride: "all-brokers-az1", + }, + }, + "az2": { + EnvoyConfig: &v1beta1.EnvoyConfig{ + Annotations: map[string]string{"zone": "az2"}, + BrokerHostnameTemplate: "broker-%id", + }, + IngressServiceSettings: v1beta1.IngressServiceSettings{ + HostnameOverride: "all-brokers-az2", + }, + }, + }, + } + kafkaCluster.Spec.ListenersConfig.ExternalListeners[0] = testExternalListener + }) + JustBeforeEach(func(ctx SpecContext) { + By("creating namespace " + namespace) + err := k8sClient.Create(ctx, namespaceObj) + Expect(err).NotTo(HaveOccurred()) + + By("creating kafka cluster object " + kafkaCluster.Name + " in namespace " + namespace) + err = k8sClient.Create(ctx, kafkaCluster) + Expect(err).NotTo(HaveOccurred()) + + waitForClusterRunningState(ctx, kafkaCluster, namespace) + }) + + When("configuring two ingress envoy controller config inside the external listener using both as bindings", func() { + BeforeEach(func() { + kafkaCluster.Spec.Brokers[0].BrokerConfig = &v1beta1.BrokerConfig{BrokerIngressMapping: []string{"az1"}} + kafkaCluster.Spec.Brokers[1].BrokerConfig = &v1beta1.BrokerConfig{BrokerIngressMapping: []string{"az2"}} + }) + It("should reconcile object properly", func() { + expectEnvoyWithConfigAz1Tls(kafkaCluster) + expectEnvoyWithConfigAz2Tls(kafkaCluster) + expectBrokerConfigmapForAz1ExternalListenerTls(kafkaCluster, count) + expectBrokerConfigmapForAz2ExternalListenerTls(kafkaCluster, count) + }) + }) +}) + func expectKafkaMonitoring(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster) { configMap := corev1.ConfigMap{} configMapName := fmt.Sprintf("%s-kafka-jmx-exporter", kafkaCluster.Name) diff --git a/controllers/tests/kafkatopic_controller_test.go b/controllers/tests/kafkatopic_controller_test.go index 20f5a1ba9..1551e156f 100644 --- a/controllers/tests/kafkatopic_controller_test.go +++ b/controllers/tests/kafkatopic_controller_test.go @@ -22,7 +22,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" diff --git a/controllers/tests/kafkauser_controller_test.go b/controllers/tests/kafkauser_controller_test.go index 522f87ba8..6fe01b72e 100644 --- a/controllers/tests/kafkauser_controller_test.go +++ b/controllers/tests/kafkauser_controller_test.go @@ -25,7 +25,7 @@ import ( . "github.com/onsi/gomega" apierrors "k8s.io/apimachinery/pkg/api/errors" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" certsigningreqv1 "k8s.io/api/certificates/v1" corev1 "k8s.io/api/core/v1" diff --git a/controllers/tests/mocks/scale.go b/controllers/tests/mocks/scale.go index 9fb0fd29e..e5a6057ba 100644 --- a/controllers/tests/mocks/scale.go +++ b/controllers/tests/mocks/scale.go @@ -280,6 +280,21 @@ func (mr *MockCruiseControlScalerMockRecorder) RemoveBrokersWithParams(ctx, para return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveBrokersWithParams", reflect.TypeOf((*MockCruiseControlScaler)(nil).RemoveBrokersWithParams), ctx, params) } +// RemoveDisksWithParams mocks base method. +func (m *MockCruiseControlScaler) RemoveDisksWithParams(ctx context.Context, params map[string]string) (*scale.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveDisksWithParams", ctx, params) + ret0, _ := ret[0].(*scale.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveDisksWithParams indicates an expected call of RemoveDisksWithParams. +func (mr *MockCruiseControlScalerMockRecorder) RemoveDisksWithParams(ctx, params interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveDisksWithParams", reflect.TypeOf((*MockCruiseControlScaler)(nil).RemoveDisksWithParams), ctx, params) +} + // Status mocks base method. func (m *MockCruiseControlScaler) Status(ctx context.Context) (scale.StatusTaskResult, error) { m.ctrl.T.Helper() diff --git a/controllers/tests/suite_test.go b/controllers/tests/suite_test.go index dac061e24..d7faf203e 100644 --- a/controllers/tests/suite_test.go +++ b/controllers/tests/suite_test.go @@ -50,6 +50,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" @@ -132,10 +134,14 @@ var _ = BeforeSuite(func(ctx SpecContext) { Expect(csrClient).NotTo(BeNil()) mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: "0", - LeaderElection: false, - Port: 8443, + Scheme: scheme, + Metrics: server.Options{ + BindAddress: "0", + }, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: 8443, + }), + LeaderElection: false, }) Expect(err).ToNot(HaveOccurred()) Expect(mgr).ToNot(BeNil()) diff --git a/docker/kafka/Dockerfile b/docker/kafka/Dockerfile new file mode 100644 index 000000000..07b0b797f --- /dev/null +++ b/docker/kafka/Dockerfile @@ -0,0 +1,126 @@ +FROM alpine:latest AS kafka_dist + +ARG scala_version=2.13 +ARG kafka_version=3.6.1 +ARG kafka_distro_base_url=https://downloads.apache.org/kafka + +ENV kafka_distro=kafka_$scala_version-$kafka_version.tgz +ENV kafka_distro_asc=$kafka_distro.asc + +RUN apk add --no-cache gnupg + +WORKDIR /var/tmp + +RUN wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro +RUN wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro_asc +RUN wget -q $kafka_distro_base_url/KEYS + +RUN gpg --import KEYS +RUN gpg --verify $kafka_distro_asc $kafka_distro + +RUN tar -xzf $kafka_distro +RUN rm -r kafka_$scala_version-$kafka_version/bin/windows + + +# backported from https://github.com/docker-library/openjdk/blob/master/18/jdk/slim-bullseye/Dockerfile +FROM debian:bullseye-slim + +ARG scala_version=2.13 +ARG kafka_version=3.6.1 + + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates p11-kit \ + ; \ + rm -rf /var/lib/apt/lists/* + +ENV JAVA_HOME /usr/local/openjdk-21 +ENV PATH $JAVA_HOME/bin:$PATH + +# Default to UTF-8 file.encoding +ENV LANG C.UTF-8 +ENV JAVA_VERSION 21 + +RUN set -eux; \ + \ + arch="$(dpkg --print-architecture)"; \ + case "$arch" in \ + 'amd64') \ + downloadUrl='https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz'; \ + downloadSha256='https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz.sha256'; \ + ;; \ + 'arm64') \ + downloadUrl='https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz'; \ + downloadSha256='https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz.sha256'; \ + ;; \ + *) echo >&2 "error: unsupported architecture: '$arch'"; exit 1 ;; \ + esac; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + wget --progress=dot:giga -O openjdk.tgz "$downloadUrl"; \ + SHA256=$(wget -qO- $downloadSha256) ; \ + echo "$SHA256 *openjdk.tgz" | sha256sum --strict --check -; \ + \ + mkdir -p "$JAVA_HOME"; \ + tar --extract \ + --file openjdk.tgz \ + --directory "$JAVA_HOME" \ + --strip-components 1 \ + --no-same-owner \ + ; \ + rm openjdk.tgz*; \ + \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# update "cacerts" bundle to use Debian's CA certificates (and make sure it stays up-to-date with changes to Debian's store) +# see https://github.com/docker-library/openjdk/issues/327 +# http://rabexc.org/posts/certificates-not-working-java#comment-4099504075 +# https://salsa.debian.org/java-team/ca-certificates-java/blob/3e51a84e9104823319abeb31f880580e46f45a98/debian/jks-keystore.hook.in +# https://git.alpinelinux.org/aports/tree/community/java-cacerts/APKBUILD?id=761af65f38b4570093461e6546dcf6b179d2b624#n29 + { \ + echo '#!/usr/bin/env bash'; \ + echo 'set -Eeuo pipefail'; \ + echo 'trust extract --overwrite --format=java-cacerts --filter=ca-anchors --purpose=server-auth "$JAVA_HOME/lib/security/cacerts"'; \ + } > /etc/ca-certificates/update.d/docker-openjdk; \ + chmod +x /etc/ca-certificates/update.d/docker-openjdk; \ + /etc/ca-certificates/update.d/docker-openjdk; \ + \ +# https://github.com/docker-library/openjdk/issues/331#issuecomment-498834472 + find "$JAVA_HOME/lib" -name '*.so' -exec dirname '{}' ';' | sort -u > /etc/ld.so.conf.d/docker-openjdk.conf; \ + ldconfig; \ + \ +# https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840 +# https://openjdk.java.net/jeps/341 + java -Xshare:dump; \ + \ +# basic smoke test + fileEncoding="$(echo 'System.out.println(System.getProperty("file.encoding"))' | jshell -s -)"; [ "$fileEncoding" = 'UTF-8' ]; rm -rf ~/.java; \ + javac --version; \ + java --version + +ENV KAFKA_VERSION=$kafka_version \ + SCALA_VERSION=$scala_version \ + KAFKA_HOME=/opt/kafka + +ENV PATH=${PATH}:${KAFKA_HOME}/bin + +RUN mkdir ${KAFKA_HOME} && apt-get update && apt-get -y upgrade && apt-get install curl -y && apt-get clean + +COPY --from=kafka_dist /var/tmp/kafka_$scala_version-$kafka_version ${KAFKA_HOME} +COPY opt/kafka/config/log4j.properties ${KAFKA_HOME}/config/log4j.properties + + +RUN chmod a+x ${KAFKA_HOME}/bin/*.sh +RUN chmod g+rwX ${KAFKA_HOME} && mkdir -p ${KAFKA_HOME}/libs/extensions && chmod g+rwX ${KAFKA_HOME}/libs/extensions + +CMD ["kafka-server-start.sh"] diff --git a/docker/kafka/README.md b/docker/kafka/README.md new file mode 100644 index 000000000..67a9fbf53 --- /dev/null +++ b/docker/kafka/README.md @@ -0,0 +1,13 @@ +# Kafka docker image + +`adobe/kafka` docker image build configuration. + +A new `kafka-*` tag created in this repo triggers the image build and push to [adobe/kafka](https://hub.docker.com/r/adobe/kafka/tags?page=1&ordering=last_updated) docker hub repo. + +Tags should be `kafka--` e.g `kafak-2.13-2.6.2` + +# Upstream base + +This is based on [wurstmeister/kafka-docker](https://github.com/wurstmeister/kafka-docker) with the following additions: +1. Use `openjdk 17` in order to support container based resource monitoring +2. Use custom `log4j.properties` to get all kafka logs to stdout only diff --git a/docker/kafka/opt/kafka/config/log4j.properties b/docker/kafka/opt/kafka/config/log4j.properties new file mode 100644 index 000000000..c56208444 --- /dev/null +++ b/docker/kafka/opt/kafka/config/log4j.properties @@ -0,0 +1,50 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Unspecified loggers and loggers with additivity=true output to server.log and stdout +# Note that INFO only applies to unspecified loggers, the log level of the child logger is used otherwise +log4j.rootLogger=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c)%n + +# Change the line below to adjust ZK client logging +log4j.logger.org.apache.zookeeper=INFO + +# Change the two lines below to adjust the general broker logging level (output to server.log and stdout) +log4j.logger.kafka=INFO +log4j.logger.org.apache.kafka=INFO + +# Change to DEBUG or TRACE to enable request logging +log4j.logger.kafka.request.logger=WARN + +# Uncomment the lines below and change log4j.logger.kafka.network.RequestChannel$ to TRACE for additional output +# related to the handling of requests +#log4j.logger.kafka.network.Processor=TRACE, requestAppender +#log4j.logger.kafka.server.KafkaApis=TRACE, requestAppender +# +log4j.logger.kafka.network.RequestChannel$=WARN + +log4j.logger.kafka.controller=DEBUG + + +log4j.logger.kafka.log.LogCleaner=INFO + + +log4j.logger.state.change.logger=INFO + +# Access denials are logged at INFO level, change to DEBUG to also log allowed accesses +log4j.logger.kafka.authorizer.logger=INFO diff --git a/docs/benchmarks/loadgens/Dockerfile b/docs/benchmarks/loadgens/Dockerfile index b4101c619..9a526ca91 100644 --- a/docs/benchmarks/loadgens/Dockerfile +++ b/docs/benchmarks/loadgens/Dockerfile @@ -15,7 +15,7 @@ WORKDIR /build/sangrenel RUN go mod download && go build -o /sangrenel -FROM alpine:3.16 +FROM alpine:3.18 RUN apk add --update --no-cache ca-certificates tzdata curl bash diff --git a/go.mod b/go.mod index 106c421c3..be99ba78c 100644 --- a/go.mod +++ b/go.mod @@ -1,142 +1,149 @@ module github.com/banzaicloud/koperator -go 1.19 +go 1.21 require ( + dario.cat/mergo v1.0.0 emperror.dev/errors v0.8.1 + github.com/IBM/sarama v1.42.1 github.com/Masterminds/sprig/v3 v3.2.3 - github.com/Shopify/sarama v1.36.0 github.com/banzaicloud/go-cruise-control v0.6.0 github.com/banzaicloud/istio-client-go v0.0.17 - github.com/banzaicloud/istio-operator/api/v2 v2.15.1 + github.com/banzaicloud/istio-operator/api/v2 v2.17.2 github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/banzaicloud/koperator/api v0.28.8 github.com/banzaicloud/koperator/properties v0.4.1 - github.com/cert-manager/cert-manager v1.11.2 - github.com/cisco-open/cluster-registry-controller/api v0.2.5 - github.com/envoyproxy/go-control-plane v0.10.3 - github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 - github.com/go-logr/logr v1.2.4 - github.com/imdario/mergo v0.3.13 - github.com/onsi/ginkgo/v2 v2.9.2 - github.com/onsi/gomega v1.27.6 - github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1 - github.com/prometheus/common v0.37.0 - github.com/stretchr/testify v1.8.1 - go.uber.org/mock v0.2.0 - go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 - google.golang.org/protobuf v1.28.1 + github.com/cert-manager/cert-manager v1.13.2 + github.com/cisco-open/cluster-registry-controller/api v0.2.12 + github.com/envoyproxy/go-control-plane v0.11.1 + github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 + github.com/go-logr/logr v1.3.0 + github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/gomega v1.30.0 + github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 + github.com/prometheus/common v0.45.0 + github.com/stretchr/testify v1.8.4 + go.uber.org/mock v0.3.0 + go.uber.org/zap v1.26.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa + google.golang.org/protobuf v1.31.0 gopkg.in/inf.v0 v0.9.1 gotest.tools v2.2.0+incompatible - k8s.io/api v0.26.4 - k8s.io/apiextensions-apiserver v0.26.4 - k8s.io/apimachinery v0.26.4 - k8s.io/client-go v0.26.4 - sigs.k8s.io/controller-runtime v0.14.6 + k8s.io/api v0.28.4 + k8s.io/apiextensions-apiserver v0.28.4 + k8s.io/apimachinery v0.28.4 + k8s.io/client-go v0.28.4 + sigs.k8s.io/controller-runtime v0.16.3 ) require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/tools v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 // indirect ) require ( github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.0 // indirect - github.com/banzaicloud/operator-tools v0.28.0 + github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/banzaicloud/operator-tools v0.28.10 github.com/beorn7/perks v1.0.1 // indirect - github.com/briandowns/spinner v1.12.0 // indirect - github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect + github.com/briandowns/spinner v1.23.0 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc // indirect + github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/cppforlife/go-patch v0.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/eapache/go-resiliency v1.3.0 // indirect - github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/eapache/go-resiliency v1.4.0 // indirect + github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect github.com/eapache/queue v1.1.0 // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/envoyproxy/protoc-gen-validate v0.6.7 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/zapr v1.2.3 // 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.19.14 // 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.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/huandu/xstrings v1.3.3 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/iancoleman/orderedmap v0.2.0 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect - github.com/jcmturner/gokrb5/v8 v8.4.3 // indirect + github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // 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/pierrec/lz4/v4 v4.1.17 // indirect + github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/shopspring/decimal v1.2.0 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/tidwall/gjson v1.9.3 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect - github.com/wayneashleyberry/terminal-dimensions v1.0.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd // indirect + google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - istio.io/api v0.0.0-20220817131511-59047e057639 // indirect - k8s.io/component-base v0.26.4 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 // indirect - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect - sigs.k8s.io/gateway-api v0.6.0 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + istio.io/api v1.19.0-alpha.1 // indirect + k8s.io/component-base v0.28.4 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/gateway-api v0.8.0 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) replace ( + github.com/banzaicloud/go-cruise-control => github.com/adobe/go-cruise-control v0.6.1-adbe + github.com/banzaicloud/koperator/api => ./api + github.com/banzaicloud/koperator/properties => ./properties github.com/gogo/protobuf => github.com/waynz0r/protobuf v1.3.3-0.20210811122234-64636cae0910 - github.com/golang/protobuf => github.com/luciferinlove/protobuf v0.0.0-20220913214010-c63936d75066 + github.com/golang/protobuf => github.com/luciferinlove/protobuf v1.5.2-bzc ) + +// exclude github.com/imdario/mergo v0.3.6 diff --git a/go.sum b/go.sum index ee7951bc7..726c25bc9 100644 --- a/go.sum +++ b/go.sum @@ -1,255 +1,145 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -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/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/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/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= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= emperror.dev/errors v0.8.0/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= 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/IBM/sarama v1.42.1 h1:wugyWa15TDEHh2kvq2gAy1IHLjEjuYOYgXz/ruC/OSQ= +github.com/IBM/sarama v1.42.1/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +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/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/sarama v1.36.0 h1:0OJs3eCcnezkWniVjwBbCJVaa0B1k7ImCRS3WN6NsSk= -github.com/Shopify/sarama v1.36.0/go.mod h1:9glG3eX83tgVYJ5aVtrjVUnEsOPqQIBGx1BWfN+X51I= -github.com/Shopify/toxiproxy/v2 v2.4.0 h1:O1e4Jfvr/hefNTNu+8VtdEG5lSeamJRo4aKhMOKNM64= -github.com/Shopify/toxiproxy/v2 v2.4.0/go.mod h1:3ilnjng821bkozDRxNoo64oI/DKqM+rOyJzb564+bvg= -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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/banzaicloud/go-cruise-control v0.6.0 h1:9hJrL+TRHB5uYk6Y3vML0nUVMuhcpxNVp56yqEsqYTM= -github.com/banzaicloud/go-cruise-control v0.6.0/go.mod h1:52C8XiTZjSmFVD+y76rd2al//GTJk9mSwkcHs2LGSvA= +github.com/adobe/go-cruise-control v0.6.1-adbe h1:dTarO7nW+JrFdIIKHVvayoosUdszhTj63upa44Ytj2A= +github.com/adobe/go-cruise-control v0.6.1-adbe/go.mod h1:S2hrm4FrQTvwg/MNzm2P1W1U2TuSw9YI/AQ9kDQiScY= github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= -github.com/banzaicloud/istio-operator/api/v2 v2.15.1 h1:BZg8COvoOJtfx/dgN7KpoOnce0LxDrElNHbvxNySs6g= -github.com/banzaicloud/istio-operator/api/v2 v2.15.1/go.mod h1:5qCpwWlIfxiLvBfTvT2mD2wp5RlFCDEt8Xql4sYPNBc= +github.com/banzaicloud/istio-operator/api/v2 v2.17.2 h1:dvzPxXWALiCjaxseE/oK4yWfGAlmM/BQtJT4uaEbBWg= +github.com/banzaicloud/istio-operator/api/v2 v2.17.2/go.mod h1:IEAImvDm2L4sY3hnNpsImg3ElcAY73KERmA+xoKVpW8= github.com/banzaicloud/k8s-objectmatcher v1.8.0 h1:Nugn25elKtPMTA2br+JgHNeSQ04sc05MDPmpJnd1N2A= github.com/banzaicloud/k8s-objectmatcher v1.8.0/go.mod h1:p2LSNAjlECf07fbhDyebTkPUIYnU05G+WfGgkTmgeMg= -github.com/banzaicloud/koperator/api v0.28.8 h1:7J6B+s9D5WhTNKC5oQwk4USN4h2gUP4GLfNmfq2yb1c= -github.com/banzaicloud/koperator/api v0.28.8/go.mod h1:AGGQ+aTBklaaG8ErotNPlP/nS47MYLc/jFVW7AsDiEE= -github.com/banzaicloud/koperator/properties v0.4.1 h1:SB2QgXlcK1Dc7Z1rg65PJifErDa8OQnoWCCJgmC7SGc= -github.com/banzaicloud/koperator/properties v0.4.1/go.mod h1:TcL+llxuhW3UeQtVEDYEXGouFLF2P+LuZZVudSb6jyA= -github.com/banzaicloud/operator-tools v0.28.0 h1:GSfc0qZr6zo7WrNxdgWZE1LcTChPU8QFYOTDirYVtIM= -github.com/banzaicloud/operator-tools v0.28.0/go.mod h1:t0dyFGJUR9Q5CwsUcq1nDJC0wSZqeh6nzUZkUp3vCXg= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/banzaicloud/operator-tools v0.28.10 h1:mm+LvL31GV9BL//zs/CTKVcFdHHyZ+KIbuNoXrOo3gA= +github.com/banzaicloud/operator-tools v0.28.10/go.mod h1:PhwQ6bn1blX+SuH5ALj3Fwvvmsi1KdAwke8NufILY8I= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -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/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= -github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= +github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cert-manager/cert-manager v1.11.2 h1:rJMZv9VtN0YhHZn1esj+V0+KhrYUF8d0BMJWUeIrKX4= -github.com/cert-manager/cert-manager v1.11.2/go.mod h1:hZshV9rYSanOsbRcQHyRmrvhtq/pj0L9+Hg10Do9NgI= -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/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cert-manager/cert-manager v1.13.2 h1:LG8+OLvxtc49CSyfjW7zHSyvlt7JVaHgRGyhfdvPpkk= +github.com/cert-manager/cert-manager v1.13.2/go.mod h1:AdfSU8muS+bj3C46YaD1VrlpXh672z5MeW/k1k5Sl1w= 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/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/cisco-open/cluster-registry-controller/api v0.2.5 h1:ylJwxnOXlgjoAPYmwNGoFl8Ja4rHBQzAlnoDIkP30lA= -github.com/cisco-open/cluster-registry-controller/api v0.2.5/go.mod h1:+SGsAzdHbD+v+CovGDNqbfEg48p/EiopbLvYZj56Vgg= +github.com/cisco-open/cluster-registry-controller/api v0.2.12 h1:dxKVG3T75RAU8f0kmeLRh82Ao4koTFIPZEodUTBhg14= +github.com/cisco-open/cluster-registry-controller/api v0.2.12/go.mod h1:zRJ4y4xZlEq1AkOm8pd6qpH7WQ9yinLaE3SA30TWh74= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc h1:PYXxkRUBGUMa5xgMVMDl62vEklZvKpVaxQeN9ie7Hfk= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cppforlife/go-patch v0.2.0 h1:Y14MnCQjDlbw7WXT4k+u6DPAA9XnygN4BfrSpI/19RU= github.com/cppforlife/go-patch v0.2.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/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/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0= +github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 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/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.3 h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7 h1:qcZcULcd/abmQg6dwigimCNEyi4gg31M/xaciQlDml8= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch v4.9.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/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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= -github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= -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-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/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= +github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= 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.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -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/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -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/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.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -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/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/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 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/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= 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-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/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/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/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +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.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.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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/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/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-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.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.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/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -258,20 +148,18 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= -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.11/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/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= @@ -280,61 +168,42 @@ github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVET github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.3 h1:iTonLeSJOn7MVUtyMT+arAn5AKAPrkilzhGw8wE/Tq8= -github.com/jcmturner/gokrb5/v8 v8.4.3/go.mod h1:dqRwJGXznQrzw6cWmyo6kH+E7jksEQG/CyVWsJEsJO0= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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.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/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.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.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -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.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/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 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/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/luciferinlove/protobuf v0.0.0-20220913214010-c63936d75066 h1:BQKOM2ATglKs0TQ55cJ/PDzqKjpzJ8P8UANBeifLHdY= -github.com/luciferinlove/protobuf v0.0.0-20220913214010-c63936d75066/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/luciferinlove/protobuf v1.5.2-bzc h1:gqDhIaLi4fSgPX8fhirNqShQCz5K8PREqgzERy2hKOg= +github.com/luciferinlove/protobuf v1.5.2-bzc/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -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-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -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/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -351,85 +220,51 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 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.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= -github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= +github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= 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.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1 h1:FyBdsRqqHH4LctMLL+BL2oGO+ONcIPwn96ctofCVtNE= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= -github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 h1:2nosf3P75OZv2/ZO/9Px5ZgZ5gbKrzA3joN1QMfOGMQ= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -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.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -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-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/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/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -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/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -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/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/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/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.1.1/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= @@ -441,242 +276,127 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +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/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/wayneashleyberry/terminal-dimensions v1.0.0 h1:LawtS1nqKjAfqrmKOzkcrDLAjSzh38lEhC401JPjQVA= -github.com/wayneashleyberry/terminal-dimensions v1.0.0/go.mod h1:PW2XrtV6KmKOPhuf7wbtcmw1/IFnC39mryRET2XbxeE= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/wayneashleyberry/terminal-dimensions v1.1.0 h1:EB7cIzBdsOzAgmhTUtTTQXBByuPheP/Zv1zL2BRPY6g= +github.com/wayneashleyberry/terminal-dimensions v1.1.0/go.mod h1:2lc/0eWCObmhRczn2SdGSQtgBooLUzIotkkEGXqghyg= github.com/waynz0r/protobuf v1.3.3-0.20210811122234-64636cae0910 h1:USK8UCHlf1voJ4u9rLI6Ot4WwXk3aPXIDz9q+PDrjpo= github.com/waynz0r/protobuf v1.3.3-0.20210811122234-64636cae0910/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -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 v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -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.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= -go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= -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/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +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= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= 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/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -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/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 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-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.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-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-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-20191002035440-2ec189313ef0/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-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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -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-20211112202133-69e39bad7dc2/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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= -golang.org/x/net v0.0.0-20220809184613-07c6da5e1ced/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= 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-20210514164344-f6687ab2804c/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.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-20190606165138-5da285871e9c/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-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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/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-20200122134326-e047566fdf82/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-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-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-20200803210538-64077c9b5642/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210603081109-ebe580a85c40/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-20210630005230-0f9fa26af87c/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-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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= 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.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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -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/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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= @@ -684,150 +404,47 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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-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-20190621195816-6e04913cbbac/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-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-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-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-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= 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= -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.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= +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.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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/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-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-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-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-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd h1:OjndDrsik+Gt+e6fs45z9AxiewiKyLKYpA45W5Kpkks= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= +google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 h1:o4LtQxebKIJ4vkzyhtD2rfUNZ20Zf0ik5YVP5E7G7VE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -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.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -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/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.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-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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -836,65 +453,51 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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= 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= -istio.io/api v0.0.0-20220817131511-59047e057639 h1:TaIQUBRFkrgmQELp2YGiDxMdl1/c1AW/JHbAZ5MWhdw= -istio.io/api v0.0.0-20220817131511-59047e057639/go.mod h1:hQkF0Q19MCmfOTre/Sg4KvrwwETq45oaFplnBm2p4j8= -k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94= -k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk= -k8s.io/apiextensions-apiserver v0.26.4 h1:9D2RTxYGxrG5uYg6D7QZRcykXvavBvcA59j5kTaedQI= -k8s.io/apiextensions-apiserver v0.26.4/go.mod h1:cd4uGFGIgzEqUghWpRsr9KE8j2KNTjY8Ji8pnMMazyw= +istio.io/api v1.19.0-alpha.1 h1:piKxgZ1Y9abNin/zw9cp6AFKhhC3Z2UmJRTN0Tm5FEY= +istio.io/api v1.19.0-alpha.1/go.mod h1:dDMe1TsOtrRoUlBzdxqNolWXpXPQjLfbcXvqPMtQ6eo= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= +k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= +k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= -k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.26.4 h1:/7P/IbGBuT73A+G97trf44NTPSNqvuBREpOfdLbHvD4= -k8s.io/client-go v0.26.4/go.mod h1:6qOItWm3EwxJdl/8p5t7FWtWUOwyMdA8N9ekbW4idpI= -k8s.io/component-base v0.26.4 h1:Bg2xzyXNKL3eAuiTEu3XE198d6z22ENgFgGQv2GGOUk= -k8s.io/component-base v0.26.4/go.mod h1:lTuWL1Xz/a4e80gmIC3YZG2JCO4xNwtKWHJWeJmsq20= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= +k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo= +k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 h1:tBEbstoM+K0FiBV5KGAKQ0kuvf54v/hwpldiJt69w1s= -k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -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/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/gateway-api v0.6.0 h1:v2FqrN2ROWZLrSnI2o91taHR8Sj3s+Eh3QU7gLNWIqA= -sigs.k8s.io/gateway-api v0.6.0/go.mod h1:EYJT+jlPWTeNskjV0JTki/03WX1cyAnBhwBJfYHpV/0= -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= +k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f h1:eeEUOoGYWhOz7EyXqhlR2zHKNw2mNJ9vzJmub6YN6kk= +k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= +sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +sigs.k8s.io/gateway-api v0.8.0 h1:isQQ3Jx2qFP7vaA3ls0846F0Amp9Eq14P08xbSwVbQg= +sigs.k8s.io/gateway-api v0.8.0/go.mod h1:okOnjPNBFbIS/Rw9kAhuIUaIkLhTKEu+ARIuXk2dgaM= +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.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -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/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= 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= diff --git a/hack/kafka-test-pod/Dockerfile b/hack/kafka-test-pod/Dockerfile index 2e26fa9df..447b42a1a 100644 --- a/hack/kafka-test-pod/Dockerfile +++ b/hack/kafka-test-pod/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19 as builder +FROM golang:1.21 as builder WORKDIR /workspace diff --git a/hack/kafka-test-pod/main.go b/hack/kafka-test-pod/main.go index 88b421b42..2eec5d448 100644 --- a/hack/kafka-test-pod/main.go +++ b/hack/kafka-test-pod/main.go @@ -23,7 +23,7 @@ import ( "syscall" "time" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" ) const kafkaTopic = "test-topic" diff --git a/internal/alertmanager/currentalert/current_alerts_test.go b/internal/alertmanager/currentalert/current_alerts_test.go index c6f4762d3..7af13d17e 100644 --- a/internal/alertmanager/currentalert/current_alerts_test.go +++ b/internal/alertmanager/currentalert/current_alerts_test.go @@ -141,10 +141,10 @@ func TestGetCurrentAlerts(t *testing.T) { ListenersConfig: v1beta1.ListenersConfig{ InternalListeners: []v1beta1.InternalListenerConfig{ {CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "plaintext", - ContainerPort: 29092}, - UsedForInnerBrokerCommunication: true, + Type: "plaintext", + Name: "plaintext", + ContainerPort: 29092, + UsedForInnerBrokerCommunication: true}, }, }, }, diff --git a/main.go b/main.go index b3a0a6a1a..4aa93c4e9 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" istioclientv1beta1 "github.com/banzaicloud/istio-client-go/pkg/networking/v1beta1" @@ -111,7 +113,6 @@ func main() { // adding indexers to KafkaTopics so that the KafkaTopic admission webhooks could work ctx := context.Background() - var managerWatchCacheBuilder cache.NewCacheFunc // When operator is started to watch resources in a specific set of namespaces, we use the MultiNamespacedCacheBuilder cache. // In this scenario, it is also suggested to restrict the provided authorization to this namespace by replacing the default @@ -119,23 +120,27 @@ func main() { // For further information see the kubernetes documentation about // Using [RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/). var namespaceList []string + watchedNamespaces := make(map[string]cache.Config) if namespaces != "" { namespaceList = strings.Split(namespaces, ",") for i := range namespaceList { - namespaceList[i] = strings.TrimSpace(namespaceList[i]) + watchedNamespaces[strings.TrimSpace(namespaceList[i])] = cache.Config{} } - managerWatchCacheBuilder = cache.MultiNamespacedCacheBuilder(namespaceList) } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "controller-leader-election-helper", - NewCache: managerWatchCacheBuilder, - Port: webhookServerPort, - CertDir: webhookCertDir, + Scheme: scheme, + LeaderElection: enableLeaderElection, + LeaderElectionID: "controller-leader-election-helper", + WebhookServer: webhook.NewServer(webhook.Options{ + Port: webhookServerPort, + CertDir: webhookCertDir, + }), HealthProbeBindAddress: healthProbesAddr, + Metrics: server.Options{ + BindAddress: metricsAddr, + }, + Cache: cache.Options{DefaultNamespaces: watchedNamespaces}, }) if err != nil { setupLog.Error(err, "unable to start manager") diff --git a/pkg/k8sutil/status.go b/pkg/k8sutil/status.go index 035eb3617..5ba4a68a8 100644 --- a/pkg/k8sutil/status.go +++ b/pkg/k8sutil/status.go @@ -29,6 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "github.com/banzaicloud/koperator/api/v1beta1" banzaicloudv1beta1 "github.com/banzaicloud/koperator/api/v1beta1" "github.com/banzaicloud/koperator/pkg/util" clientutil "github.com/banzaicloud/koperator/pkg/util/client" @@ -178,8 +179,8 @@ func generateBrokerState(brokerIDs []string, cluster *banzaicloudv1beta1.KafkaCl cluster.Status.BrokersState = brokersState } -// DeleteStatus deletes the given broker state from the CR -func DeleteStatus(c client.Client, brokerID string, cluster *banzaicloudv1beta1.KafkaCluster, logger logr.Logger) error { +// DeleteBrokerStatus deletes the given broker state from the CR +func DeleteBrokerStatus(c client.Client, brokerID string, cluster *banzaicloudv1beta1.KafkaCluster, logger logr.Logger) error { typeMeta := cluster.TypeMeta brokerStatus := cluster.Status.BrokersState @@ -223,6 +224,55 @@ func DeleteStatus(c client.Client, brokerID string, cluster *banzaicloudv1beta1. return nil } +// DeleteVolumeStatus deletes the given volume state for the given broker from the CR +func DeleteVolumeStatus(c client.Client, brokerID string, mountPath string, cluster *banzaicloudv1beta1.KafkaCluster, logger logr.Logger) error { + typeMeta := cluster.TypeMeta + + brokerStatus := cluster.Status.BrokersState + + if status, ok := brokerStatus[brokerID]; ok { + delete(status.GracefulActionState.VolumeStates, mountPath) + } + + cluster.Status.BrokersState = brokerStatus + + err := c.Status().Update(context.Background(), cluster) + if apierrors.IsNotFound(err) { + err = c.Update(context.Background(), cluster) + } + if err != nil { + if !apierrors.IsConflict(err) { + return errors.WrapIff(err, "could not delete Kafka cluster broker %s volume %s state ", brokerID, mountPath) + } + err := c.Get(context.TODO(), types.NamespacedName{ + Namespace: cluster.Namespace, + Name: cluster.Name, + }, cluster) + if err != nil { + return errors.WrapIf(err, "could not get config for updating status") + } + brokerStatus = cluster.Status.BrokersState + + if status, ok := brokerStatus[brokerID]; ok { + delete(status.GracefulActionState.VolumeStates, mountPath) + } + + cluster.Status.BrokersState = brokerStatus + err = c.Status().Update(context.Background(), cluster) + if apierrors.IsNotFound(err) { + err = c.Update(context.Background(), cluster) + } + if err != nil { + return errors.WrapIff(err, "could not delete Kafka clusters broker %s volume %s state ", brokerID, mountPath) + } + } + + // update loses the typeMeta of the config that's used later when setting ownerrefs + cluster.TypeMeta = typeMeta + logger.Info(fmt.Sprintf("Kafka broker %s volume %s state deleted", brokerID, mountPath)) + return nil +} + // UpdateCRStatus updates the cluster state func UpdateCRStatus(c client.Client, cluster *banzaicloudv1beta1.KafkaCluster, state interface{}, logger logr.Logger) error { typeMeta := cluster.TypeMeta @@ -354,7 +404,7 @@ func UpdateListenerStatuses(ctx context.Context, c client.Client, cluster *banza return nil } -func CreateInternalListenerStatuses(kafkaCluster *banzaicloudv1beta1.KafkaCluster) (map[string]banzaicloudv1beta1.ListenerStatusList, map[string]banzaicloudv1beta1.ListenerStatusList) { +func CreateInternalListenerStatuses(kafkaCluster *banzaicloudv1beta1.KafkaCluster, externalListenerStatus map[string]banzaicloudv1beta1.ListenerStatusList) (map[string]banzaicloudv1beta1.ListenerStatusList, map[string]banzaicloudv1beta1.ListenerStatusList) { intListenerStatuses := make(map[string]banzaicloudv1beta1.ListenerStatusList, len(kafkaCluster.Spec.ListenersConfig.InternalListeners)) controllerIntListenerStatuses := make(map[string]banzaicloudv1beta1.ListenerStatusList) @@ -374,13 +424,22 @@ func CreateInternalListenerStatuses(kafkaCluster *banzaicloudv1beta1.KafkaCluste // add addresses per broker for _, broker := range kafkaCluster.Spec.Brokers { - var address string - if kafkaCluster.Spec.HeadlessServiceEnabled { - address = fmt.Sprintf("%s-%d.%s-headless.%s.svc.%s:%d", kafkaCluster.Name, broker.Id, kafkaCluster.Name, - kafkaCluster.Namespace, kafkaCluster.Spec.GetKubernetesClusterDomain(), iListener.ContainerPort) - } else { - address = fmt.Sprintf("%s-%d.%s.svc.%s:%d", kafkaCluster.Name, broker.Id, kafkaCluster.Namespace, - kafkaCluster.Spec.GetKubernetesClusterDomain(), iListener.ContainerPort) + var address = "" + if iListener.ExternalListenerForHostname != "" && iListener.InternalStartingPort > 0 { + if eListenerStatus, ok := externalListenerStatus[iListener.ExternalListenerForHostname]; ok { + address = fmt.Sprintf("%s:%d", getHostnameForBrokerId(eListenerStatus, broker.Id), + iListener.InternalStartingPort+broker.Id) + } + } + + if address == "" { + if kafkaCluster.Spec.HeadlessServiceEnabled { + address = fmt.Sprintf("%s-%d.%s-headless.%s.svc.%s:%d", kafkaCluster.Name, broker.Id, kafkaCluster.Name, + kafkaCluster.Namespace, kafkaCluster.Spec.GetKubernetesClusterDomain(), iListener.ContainerPort) + } else { + address = fmt.Sprintf("%s-%d.%s.svc.%s:%d", kafkaCluster.Name, broker.Id, kafkaCluster.Namespace, + kafkaCluster.Spec.GetKubernetesClusterDomain(), iListener.ContainerPort) + } } listenerStatusList = append(listenerStatusList, banzaicloudv1beta1.ListenerStatus{ Name: fmt.Sprintf("broker-%d", broker.Id), @@ -397,3 +456,12 @@ func CreateInternalListenerStatuses(kafkaCluster *banzaicloudv1beta1.KafkaCluste return intListenerStatuses, controllerIntListenerStatuses } + +func getHostnameForBrokerId(eListenerStatusList v1beta1.ListenerStatusList, brokerId int32) string { + for _, eListenerStatus := range eListenerStatusList { + if eListenerStatus.Name == fmt.Sprintf("broker-%d", brokerId) { + return strings.Split(eListenerStatus.Address, ":")[0] + } + } + return "" +} diff --git a/pkg/kafkaclient/client.go b/pkg/kafkaclient/client.go index 4704b788e..5d621a673 100644 --- a/pkg/kafkaclient/client.go +++ b/pkg/kafkaclient/client.go @@ -18,7 +18,7 @@ import ( "fmt" "time" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/api/v1alpha1" "github.com/banzaicloud/koperator/api/v1beta1" "github.com/banzaicloud/koperator/pkg/errorfactory" diff --git a/pkg/kafkaclient/dynamicConfig.go b/pkg/kafkaclient/dynamicConfig.go index c8a592c89..b9dc67f50 100644 --- a/pkg/kafkaclient/dynamicConfig.go +++ b/pkg/kafkaclient/dynamicConfig.go @@ -19,7 +19,7 @@ import ( "strconv" "emperror.dev/errors" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/pkg/errorfactory" ) diff --git a/pkg/kafkaclient/mock_client.go b/pkg/kafkaclient/mock_client.go index 844c7c781..f0db30479 100644 --- a/pkg/kafkaclient/mock_client.go +++ b/pkg/kafkaclient/mock_client.go @@ -19,7 +19,7 @@ import ( "sync" "time" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/pkg/kafkaclient/topics.go b/pkg/kafkaclient/topics.go index 0cecb2847..aa3b175c7 100644 --- a/pkg/kafkaclient/topics.go +++ b/pkg/kafkaclient/topics.go @@ -19,7 +19,7 @@ import ( "fmt" "time" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/pkg/errorfactory" ) diff --git a/pkg/kafkaclient/topics_test.go b/pkg/kafkaclient/topics_test.go index 0b07e15a0..ec9c5d95a 100644 --- a/pkg/kafkaclient/topics_test.go +++ b/pkg/kafkaclient/topics_test.go @@ -17,7 +17,7 @@ package kafkaclient import ( "testing" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" ) func TestListTopics(t *testing.T) { diff --git a/pkg/kafkaclient/users.go b/pkg/kafkaclient/users.go index 054616db3..1b31a9376 100644 --- a/pkg/kafkaclient/users.go +++ b/pkg/kafkaclient/users.go @@ -17,7 +17,7 @@ package kafkaclient import ( "fmt" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/api/v1alpha1" "github.com/banzaicloud/koperator/pkg/errorfactory" ) diff --git a/pkg/kafkaclient/users_test.go b/pkg/kafkaclient/users_test.go index 6e97c3c5e..95a9a43b4 100644 --- a/pkg/kafkaclient/users_test.go +++ b/pkg/kafkaclient/users_test.go @@ -17,7 +17,7 @@ package kafkaclient import ( "testing" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/banzaicloud/koperator/api/v1alpha1" ) diff --git a/pkg/resources/envoy/configmap.go b/pkg/resources/envoy/configmap.go index a2e2a325b..ee13b2347 100644 --- a/pkg/resources/envoy/configmap.go +++ b/pkg/resources/envoy/configmap.go @@ -16,6 +16,7 @@ package envoy import ( "fmt" + "sort" envoyaccesslog "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v3" envoybootstrap "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v3" @@ -27,8 +28,11 @@ import ( envoystdoutaccesslog "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/stream/v3" envoyhttphealthcheck "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/health_check/v3" envoyhttprouter "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" + tls_inspectorv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" envoyhcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" envoytcpproxy "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" + tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + envoytypesmatcher "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" envoytypes "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" "github.com/ghodss/yaml" @@ -99,8 +103,13 @@ func generateEnvoyHealthCheckListener(ingressConfig v1beta1.IngressConfig, log l Headers: []*envoyroute.HeaderMatcher{ { Name: ":path", - HeaderMatchSpecifier: &envoyroute.HeaderMatcher_ExactMatch{ - ExactMatch: envoyutils.HealthCheckPath, + HeaderMatchSpecifier: &envoyroute.HeaderMatcher_StringMatch{ + StringMatch: &envoytypesmatcher.StringMatcher{ + IgnoreCase: true, + MatchPattern: &envoytypesmatcher.StringMatcher_Exact{ + Exact: envoyutils.HealthCheckPath, + }, + }, }, }, }, @@ -203,9 +212,92 @@ func generateEnvoyHealthCheckListener(ingressConfig v1beta1.IngressConfig, log l }, }, }, + SocketOptions: getKeepAliveSocketOptions(), } } +func GenerateEnvoyTLSFilterChain(tcpProxy *envoytcpproxy.TcpProxy, brokerFqdn string, log logr.Logger) (*envoylistener.FilterChain, error) { + tlsContext := &tlsv3.DownstreamTlsContext{ + CommonTlsContext: &tlsv3.CommonTlsContext{ + TlsParams: &tlsv3.TlsParameters{ + TlsMinimumProtocolVersion: tlsv3.TlsParameters_TLSv1_2, + TlsMaximumProtocolVersion: tlsv3.TlsParameters_TLSv1_3, + }, + TlsCertificates: []*tlsv3.TlsCertificate{ + { + CertificateChain: &envoycore.DataSource{ + Specifier: &envoycore.DataSource_Filename{ + Filename: "/certs/certificate.crt", + }, + }, + PrivateKey: &envoycore.DataSource{ + Specifier: &envoycore.DataSource_Filename{ + Filename: "/certs/private.key", + }, + }, + }, + }, + }, + } + pbTlsContext, err := anypb.New(tlsContext) + if err != nil { + log.Error(err, "could not marshall envoy tcp_proxy tls config") + return nil, err + } + + pbstTcpProxy, err := anypb.New(tcpProxy) + if err != nil { + log.Error(err, "could not marshall envoy tcp_proxy config") + return nil, err + } + + brokerTcpProxyFilter := &envoylistener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoylistener.Filter_TypedConfig{ + TypedConfig: pbstTcpProxy, + }, + } + + filterChain := &envoylistener.FilterChain{ + FilterChainMatch: &envoylistener.FilterChainMatch{ + ServerNames: []string{brokerFqdn}, + TransportProtocol: "tls", + }, + TransportSocket: &envoycore.TransportSocket{ + Name: "envoy.transport_sockets.tls", + ConfigType: &envoycore.TransportSocket_TypedConfig{ + TypedConfig: pbTlsContext, + }, + }, + Filters: []*envoylistener.Filter{ + brokerTcpProxyFilter, + }, + } + return filterChain, nil +} + +func GenerateEnvoyFilterChain(tcpProxy *envoytcpproxy.TcpProxy, log logr.Logger) (*envoylistener.FilterChain, error) { + pbstTcpProxy, err := anypb.New(tcpProxy) + if err != nil { + log.Error(err, "could not marshall envoy tcp_proxy config") + return nil, err + } + + brokerTcpProxyFilter := &envoylistener.Filter{ + Name: wellknown.TCPProxy, + ConfigType: &envoylistener.Filter_TypedConfig{ + TypedConfig: pbstTcpProxy, + }, + } + + filterChain := &envoylistener.FilterChain{ + Filters: []*envoylistener.Filter{ + brokerTcpProxyFilter, + }, + } + return filterChain, nil +} + // GenerateEnvoyConfig generate envoy configuration file func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalListenerConfig, ingressConfig v1beta1.IngressConfig, ingressConfigName, defaultIngressConfigName string, log logr.Logger) string { @@ -224,6 +316,10 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis var listeners []*envoylistener.Listener var clusters []*envoycluster.Cluster + var filterChain *envoylistener.FilterChain + var err error + + tempListeners := make(map[int32][]*envoylistener.FilterChain) for _, brokerId := range util.GetBrokerIdsFromStatusAndSpec(kc.Status.BrokersState, kc.Spec.Brokers, log) { brokerConfig, err := kafkautils.GatherBrokerConfigIfAvailable(kc.Spec, brokerId) @@ -236,46 +332,38 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis tcpProxy := &envoytcpproxy.TcpProxy{ StatPrefix: fmt.Sprintf("broker_tcp-%d", brokerId), MaxConnectAttempts: &wrapperspb.UInt32Value{Value: 2}, + IdleTimeout: &durationpb.Duration{Seconds: 560}, ClusterSpecifier: &envoytcpproxy.TcpProxy_Cluster{ Cluster: fmt.Sprintf("broker-%d", brokerId), }, } - pbstTcpProxy, err := anypb.New(tcpProxy) - if err != nil { - log.Error(err, "could not marshall envoy tcp_proxy config") - return "" + + if elistener.TLSEnabled() { + filterChain, err = GenerateEnvoyTLSFilterChain(tcpProxy, ingressConfig.EnvoyConfig.GetBrokerHostname(int32(brokerId)), log) + if err != nil { + log.Error(err, "Unable to generate broker envoy tls filter chain") + return "" + } + } else { + filterChain, err = GenerateEnvoyFilterChain(tcpProxy, log) + if err != nil { + log.Error(err, "Unable to generate broker envoy filter chain") + return "" + } } - listeners = append(listeners, &envoylistener.Listener{ - Address: &envoycore.Address{ - Address: &envoycore.Address_SocketAddress{ - SocketAddress: &envoycore.SocketAddress{ - Address: "0.0.0.0", - PortSpecifier: &envoycore.SocketAddress_PortValue{ - PortValue: uint32(elistener.ExternalStartingPort + int32(brokerId)), - }, - }, - }, - }, - FilterChains: []*envoylistener.FilterChain{ - { - Filters: []*envoylistener.Filter{ - { - Name: wellknown.TCPProxy, - ConfigType: &envoylistener.Filter_TypedConfig{ - TypedConfig: pbstTcpProxy, - }, - }, - }, - }, - }, - }) + + brokerPort := elistener.GetBrokerPort(int32(brokerId)) + tempListeners[brokerPort] = append(tempListeners[brokerPort], filterChain) clusters = append(clusters, &envoycluster.Cluster{ - Name: fmt.Sprintf("broker-%d", brokerId), - ConnectTimeout: &durationpb.Duration{Seconds: 1}, + Name: fmt.Sprintf("broker-%d", brokerId), + ConnectTimeout: &durationpb.Duration{Seconds: 1}, + UpstreamConnectionOptions: &envoycluster.UpstreamConnectionOptions{ + TcpKeepalive: getTcpKeepalive(), + }, ClusterDiscoveryType: &envoycluster.Cluster_Type{Type: envoycluster.Cluster_STRICT_DNS}, LbPolicy: envoycluster.Cluster_ROUND_ROBIN, - // disable circuit breakingL: + // disable circuit breaking: // https://www.envoyproxy.io/docs/envoy/latest/faq/load_balancing/disable_circuit_breaking CircuitBreakers: &envoycluster.CircuitBreakers{ Thresholds: []*envoycluster.CircuitBreakers_Thresholds{ @@ -320,45 +408,72 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis }) } } - // Create an any cast broker access point // TCP_Proxy filter configuration tcpProxy := &envoytcpproxy.TcpProxy{ StatPrefix: envoyutils.AllBrokerEnvoyConfigName, + IdleTimeout: &durationpb.Duration{Seconds: 560}, MaxConnectAttempts: &wrapperspb.UInt32Value{Value: 2}, ClusterSpecifier: &envoytcpproxy.TcpProxy_Cluster{ Cluster: envoyutils.AllBrokerEnvoyConfigName, }, } - pbstTcpProxy, err := anypb.New(tcpProxy) - if err != nil { - log.Error(err, "could not marshall envoy tcp_proxy config") - return "" + + // Create TLS anycast broker listener + if elistener.TLSEnabled() { + filterChain, err = GenerateEnvoyTLSFilterChain(tcpProxy, ingressConfig.HostnameOverride, log) + if err != nil { + log.Error(err, "Unable to generate anycast envoy tls filter chain") + return "" + } + } else { + filterChain, err = GenerateEnvoyFilterChain(tcpProxy, log) + if err != nil { + log.Error(err, "Unable to generate anycast envoy filter chain") + return "" + } } - listeners = append(listeners, &envoylistener.Listener{ - Address: &envoycore.Address{ - Address: &envoycore.Address_SocketAddress{ - SocketAddress: &envoycore.SocketAddress{ - Address: "0.0.0.0", - PortSpecifier: &envoycore.SocketAddress_PortValue{ - PortValue: uint32(elistener.GetIngressControllerTargetPort()), + + tempListeners[elistener.GetAnyCastPort()] = append(tempListeners[elistener.GetAnyCastPort()], filterChain) + + // sort the tempListeners map for consistent results + ports := make([]int, 0, len(tempListeners)) + for p := range tempListeners { + ports = append(ports, int(p)) + } + sort.Ints(ports) + + tlsListenerFilter := &tls_inspectorv3.TlsInspector{} + pbTlsListenerFilter, _ := anypb.New(tlsListenerFilter) + + for _, p := range ports { + newListener := &envoylistener.Listener{ + Address: &envoycore.Address{ + Address: &envoycore.Address_SocketAddress{ + SocketAddress: &envoycore.SocketAddress{ + Address: "0.0.0.0", + PortSpecifier: &envoycore.SocketAddress_PortValue{ + PortValue: uint32(p), + }, }, }, }, - }, - FilterChains: []*envoylistener.FilterChain{ - { - Filters: []*envoylistener.Filter{ - { - Name: wellknown.TCPProxy, - ConfigType: &envoylistener.Filter_TypedConfig{ - TypedConfig: pbstTcpProxy, - }, + FilterChains: tempListeners[int32(p)], + SocketOptions: getKeepAliveSocketOptions(), + } + + if elistener.TLSEnabled() { + newListener.ListenerFilters = []*envoylistener.ListenerFilter{ + { + Name: "tls_inspector", + ConfigType: &envoylistener.ListenerFilter_TypedConfig{ + TypedConfig: pbTlsListenerFilter, }, }, - }, - }, - }) + } + } + listeners = append(listeners, newListener) + } // health-check http listener healthCheckListener := generateEnvoyHealthCheckListener(ingressConfig, log) @@ -368,8 +483,11 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis listeners = append(listeners, healthCheckListener) clusters = append(clusters, &envoycluster.Cluster{ - Name: envoyutils.AllBrokerEnvoyConfigName, - ConnectTimeout: &durationpb.Duration{Seconds: 1}, + Name: envoyutils.AllBrokerEnvoyConfigName, + ConnectTimeout: &durationpb.Duration{Seconds: 1}, + UpstreamConnectionOptions: &envoycluster.UpstreamConnectionOptions{ + TcpKeepalive: getTcpKeepalive(), + }, IgnoreHealthOnHostRemoval: true, HealthChecks: []*envoycore.HealthCheck{ { @@ -459,3 +577,50 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis } return string(marshalledConfig) } + +func getTcpKeepalive() *envoycore.TcpKeepalive { + return &envoycore.TcpKeepalive{ + KeepaliveProbes: wrapperspb.UInt32(3), + KeepaliveTime: wrapperspb.UInt32(30), + KeepaliveInterval: wrapperspb.UInt32(30), + } +} + +func getKeepAliveSocketOptions() []*envoycore.SocketOption { + return []*envoycore.SocketOption{ + // enable socket keep-alive + { + // SOL_SOCKET = 1 + Level: 1, + // SO_KEEPALIVE = 9 + Name: 9, + Value: &envoycore.SocketOption_IntValue{IntValue: 1}, + State: envoycore.SocketOption_STATE_PREBIND, + }, + // configure keep alive idle, interval and count + { + // IPPROTO_TCP = 6 + Level: 6, + // TCP_KEEPIDLE = 4 + Name: 4, + Value: &envoycore.SocketOption_IntValue{IntValue: 30}, + State: envoycore.SocketOption_STATE_PREBIND, + }, + { + // IPPROTO_TCP = 6 + Level: 6, + // TCP_KEEPINTVL = 5 + Name: 5, + Value: &envoycore.SocketOption_IntValue{IntValue: 30}, + State: envoycore.SocketOption_STATE_PREBIND, + }, + { + // IPPROTO_TCP = 6 + Level: 6, + // TCP_KEEPCNT = 6 + Name: 6, + Value: &envoycore.SocketOption_IntValue{IntValue: 3}, + State: envoycore.SocketOption_STATE_PREBIND, + }, + } +} diff --git a/pkg/resources/envoy/deployment.go b/pkg/resources/envoy/deployment.go index fad72b873..c8c1e4bbe 100644 --- a/pkg/resources/envoy/deployment.go +++ b/pkg/resources/envoy/deployment.go @@ -57,7 +57,6 @@ func (r *Reconciler) deployment(log logr.Logger, extListener v1beta1.ExternalLis }, }, } - volumeMounts := []corev1.VolumeMount{ { Name: configMapName, @@ -66,6 +65,26 @@ func (r *Reconciler) deployment(log logr.Logger, extListener v1beta1.ExternalLis }, } + if extListener.TLSEnabled() && extListener.TLSSecretName != "" { + volumes = append(volumes, corev1.Volume{ + Name: "certificate", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: extListener.TLSSecretName, + Items: []corev1.KeyToPath{ + {Key: "tls.crt", Path: "certificate.crt"}, + {Key: "tls.key", Path: "private.key"}, + }, + }, + }, + }) + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: "certificate", + MountPath: "/certs", + ReadOnly: true, + }) + } + arguments := []string{"-c", "/etc/envoy/envoy.yaml"} if ingressConfig.EnvoyConfig.GetConcurrency() > 0 { arguments = append(arguments, "--concurrency", strconv.Itoa(int(ingressConfig.EnvoyConfig.GetConcurrency()))) @@ -136,10 +155,10 @@ func getExposedContainerPorts(extListener v1beta1.ExternalListenerConfig, broker log.Error(err, "could not determine brokerConfig") continue } - if util.ShouldIncludeBroker(brokerConfig, kafkaCluster.Status, brokerId, defaultIngressConfigName, ingressConfigName) { + if util.ShouldIncludeBroker(brokerConfig, kafkaCluster.Status, brokerId, defaultIngressConfigName, ingressConfigName) && !extListener.TLSEnabled() { exposedPorts = append(exposedPorts, corev1.ContainerPort{ Name: fmt.Sprintf("broker-%d", brokerId), - ContainerPort: extListener.ExternalStartingPort + int32(brokerId), + ContainerPort: extListener.GetBrokerPort(int32(brokerId)), Protocol: corev1.ProtocolTCP, }) } diff --git a/pkg/resources/envoy/service.go b/pkg/resources/envoy/service.go index 09ddc71c9..49ca52f3d 100644 --- a/pkg/resources/envoy/service.go +++ b/pkg/resources/envoy/service.go @@ -63,19 +63,21 @@ func (r *Reconciler) service(log logr.Logger, extListener v1beta1.ExternalListen func getExposedServicePorts(extListener v1beta1.ExternalListenerConfig, brokersIds []int, kafkaCluster *v1beta1.KafkaCluster, ingressConfig v1beta1.IngressConfig, ingressConfigName, defaultIngressConfigName string, log logr.Logger) []corev1.ServicePort { var exposedPorts []corev1.ServicePort - for _, brokerId := range brokersIds { - brokerConfig, err := kafkautils.GatherBrokerConfigIfAvailable(kafkaCluster.Spec, brokerId) - if err != nil { - log.Error(err, "could not determine brokerConfig") - continue - } - if util.ShouldIncludeBroker(brokerConfig, kafkaCluster.Status, brokerId, defaultIngressConfigName, ingressConfigName) { - exposedPorts = append(exposedPorts, corev1.ServicePort{ - Name: fmt.Sprintf("broker-%d", brokerId), - Port: extListener.ExternalStartingPort + int32(brokerId), - TargetPort: intstr.FromInt(int(extListener.ExternalStartingPort) + brokerId), - Protocol: corev1.ProtocolTCP, - }) + if !extListener.TLSEnabled() { + for _, brokerId := range brokersIds { + brokerConfig, err := kafkautils.GatherBrokerConfigIfAvailable(kafkaCluster.Spec, brokerId) + if err != nil { + log.Error(err, "could not determine brokerConfig") + continue + } + if util.ShouldIncludeBroker(brokerConfig, kafkaCluster.Status, brokerId, defaultIngressConfigName, ingressConfigName) { + exposedPorts = append(exposedPorts, corev1.ServicePort{ + Name: fmt.Sprintf("broker-%d", brokerId), + Port: extListener.GetBrokerPort(int32(brokerId)), + TargetPort: intstr.FromInt(int(extListener.GetBrokerPort(int32(brokerId)))), + Protocol: corev1.ProtocolTCP, + }) + } } } diff --git a/pkg/resources/istioingress/gateway.go b/pkg/resources/istioingress/gateway.go index 68d481a57..791d7919f 100644 --- a/pkg/resources/istioingress/gateway.go +++ b/pkg/resources/istioingress/gateway.go @@ -70,7 +70,7 @@ func generateServers(kc *v1beta1.KafkaCluster, externalListenerConfig v1beta1.Ex if util.ShouldIncludeBroker(brokerConfig, kc.Status, brokerId, defaultIngressConfigName, ingressConfigName) { servers = append(servers, istioclientv1beta1.Server{ Port: &istioclientv1beta1.Port{ - Number: int(externalListenerConfig.ExternalStartingPort) + brokerId, + Number: int(externalListenerConfig.GetBrokerPort(int32(brokerId))), Protocol: protocol, Name: fmt.Sprintf("tcp-broker-%d", brokerId), }, diff --git a/pkg/resources/istioingress/meshgateway.go b/pkg/resources/istioingress/meshgateway.go index f1a1ec30e..a6222196c 100644 --- a/pkg/resources/istioingress/meshgateway.go +++ b/pkg/resources/istioingress/meshgateway.go @@ -103,8 +103,8 @@ func generateExternalPorts(kc *v1beta1.KafkaCluster, brokerIds []int, generatedPorts = append(generatedPorts, &istioOperatorApi.ServicePort{ Name: fmt.Sprintf("tcp-broker-%d", brokerId), Protocol: string(corev1.ProtocolTCP), - Port: externalListenerConfig.ExternalStartingPort + int32(brokerId), - TargetPort: &istioOperatorApi.IntOrString{IntOrString: intstr.FromInt(int(externalListenerConfig.ExternalStartingPort) + brokerId)}, + Port: externalListenerConfig.GetBrokerPort(int32(brokerId)), + TargetPort: &istioOperatorApi.IntOrString{IntOrString: intstr.FromInt(int(externalListenerConfig.GetBrokerPort(int32(brokerId))))}, }) } } diff --git a/pkg/resources/istioingress/virtualservice.go b/pkg/resources/istioingress/virtualservice.go index f87d12f32..49b0186b6 100644 --- a/pkg/resources/istioingress/virtualservice.go +++ b/pkg/resources/istioingress/virtualservice.go @@ -79,7 +79,7 @@ func generateTlsRoutes(kc *v1beta1.KafkaCluster, externalListenerConfig v1beta1. tlsRoutes = append(tlsRoutes, istioclientv1beta1.TLSRoute{ Match: []istioclientv1beta1.TLSMatchAttributes{ { - Port: util.IntPointer(int(externalListenerConfig.ExternalStartingPort) + brokerId), + Port: util.IntPointer(int(externalListenerConfig.GetBrokerPort(int32(brokerId)))), SniHosts: []string{"*"}, }, }, @@ -132,7 +132,7 @@ func generateTcpRoutes(kc *v1beta1.KafkaCluster, externalListenerConfig v1beta1. tcpRoutes = append(tcpRoutes, istioclientv1beta1.TCPRoute{ Match: []istioclientv1beta1.L4MatchAttributes{ { - Port: util.IntPointer(int(externalListenerConfig.ExternalStartingPort) + brokerId), + Port: util.IntPointer(int(externalListenerConfig.GetBrokerPort(int32(brokerId)))), }, }, Route: []*istioclientv1beta1.RouteDestination{ diff --git a/pkg/resources/kafka/configmap.go b/pkg/resources/kafka/configmap.go index 33b4fdffa..5c4645c4a 100644 --- a/pkg/resources/kafka/configmap.go +++ b/pkg/resources/kafka/configmap.go @@ -15,16 +15,12 @@ package kafka import ( - "context" "fmt" "sort" "strings" "emperror.dev/errors" "github.com/go-logr/logr" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "sigs.k8s.io/controller-runtime/pkg/client" - corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" @@ -111,28 +107,11 @@ func (r *Reconciler) getConfigProperties(bConfig *v1beta1.BrokerConfig, id int32 log.Error(err, fmt.Sprintf("setting '%s' in broker configuration resulted an error", kafkautils.KafkaConfigBrokerId)) } - // This logic prevents the removal of the mountPath from the broker configmap - brokerConfigMapName := fmt.Sprintf(brokerConfigTemplate+"-%d", r.KafkaCluster.Name, id) - var brokerConfigMapOld v1.ConfigMap - err = r.Client.Get(context.Background(), client.ObjectKey{Name: brokerConfigMapName, Namespace: r.KafkaCluster.GetNamespace()}, &brokerConfigMapOld) - if err != nil && !apierrors.IsNotFound(err) { - log.Error(err, "getting broker configmap from the Kubernetes API server resulted an error") - } - - mountPathsOld, err := getMountPathsFromBrokerConfigMap(&brokerConfigMapOld) - if err != nil { - log.Error(err, "could not get mountPaths from broker configmap", v1beta1.BrokerIdLabelKey, id) - } - mountPathsNew := generateStorageConfig(bConfig.StorageConfigs) - mountPathsMerged, isMountPathRemoved := mergeMountPaths(mountPathsOld, mountPathsNew) - - if isMountPathRemoved { - log.Error(errors.New("removed storage is found in the KafkaCluster CR"), "removing storage from broker is not supported", v1beta1.BrokerIdLabelKey, id, "mountPaths", mountPathsOld, "mountPaths in kafkaCluster CR ", mountPathsNew) - } - - if len(mountPathsMerged) != 0 { - if err := config.Set(kafkautils.KafkaConfigBrokerLogDirectory, strings.Join(mountPathsMerged, ",")); err != nil { - log.Error(err, fmt.Sprintf("setting '%s' in broker configuration resulted an error", kafkautils.KafkaConfigBrokerLogDirectory)) + // Storage configuration + storageConf := generateStorageConfig(bConfig.StorageConfigs) + if len(storageConf) > 0 { + if err := config.Set(kafkautils.KafkaConfigBrokerLogDirectory, storageConf); err != nil { + log.Error(err, "setting log.dirs in broker configuration resulted an error") } } @@ -184,7 +163,7 @@ func (r *Reconciler) configMap(id int32, brokerConfig *v1beta1.BrokerConfig, ext serverPasses map[string]string, clientPass string, superUsers []string, log logr.Logger) *corev1.ConfigMap { brokerConf := &corev1.ConfigMap{ ObjectMeta: templates.ObjectMeta( - fmt.Sprintf(brokerConfigTemplate+"-%d", r.KafkaCluster.Name, id), + fmt.Sprintf(brokerConfigTemplate+"-%d", r.KafkaCluster.Name, id), //nolint:goconst apiutil.MergeLabels( apiutil.LabelsForKafka(r.KafkaCluster.Name), map[string]string{v1beta1.BrokerIdLabelKey: fmt.Sprintf("%d", id)}, @@ -202,13 +181,14 @@ func (r *Reconciler) configMap(id int32, brokerConfig *v1beta1.BrokerConfig, ext func generateAdvertisedListenerConfig(id int32, l v1beta1.ListenersConfig, extListenerStatuses, intListenerStatuses, controllerIntListenerStatuses map[string]v1beta1.ListenerStatusList) []string { - advertisedListenerConfig := make([]string, 0, len(l.ExternalListeners)+len(l.InternalListeners)) + externalListenerConfig := make([]string, 0, len(l.ExternalListeners)) + internalListenerConfig := make([]string, 0, len(l.InternalListeners)) - advertisedListenerConfig = appendListenerConfigs(advertisedListenerConfig, id, extListenerStatuses) - advertisedListenerConfig = appendListenerConfigs(advertisedListenerConfig, id, intListenerStatuses) - advertisedListenerConfig = appendListenerConfigs(advertisedListenerConfig, id, controllerIntListenerStatuses) + externalListenerConfig = appendListenerConfigs(externalListenerConfig, id, extListenerStatuses) + internalListenerConfig = appendListenerConfigs(internalListenerConfig, id, intListenerStatuses) + internalListenerConfig = appendListenerConfigs(internalListenerConfig, id, controllerIntListenerStatuses) - return advertisedListenerConfig + return append(externalListenerConfig, internalListenerConfig...) } func appendListenerConfigs(advertisedListenerConfig []string, id int32, @@ -273,6 +253,24 @@ func generateListenerSpecificConfig(l *v1beta1.ListenersConfig, serverPasses map config := properties.NewProperties() + for _, eListener := range l.ExternalListeners { + if eListener.UsedForInnerBrokerCommunication { + if interBrokerListenerName == "" { + interBrokerListenerName = strings.ToUpper(eListener.Name) + } else { + log.Error(errors.New("inter broker listener name already set"), "config error") + } + } + upperedListenerType := eListener.Type.ToUpperString() + upperedListenerName := strings.ToUpper(eListener.Name) + securityProtocolMapConfig = append(securityProtocolMapConfig, fmt.Sprintf("%s:%s", upperedListenerName, upperedListenerType)) + listenerConfig = append(listenerConfig, fmt.Sprintf("%s://:%d", upperedListenerName, eListener.ContainerPort)) + // Add external listeners SSL configuration + if eListener.Type == v1beta1.SecurityProtocolSSL { + generateListenerSSLConfig(config, eListener.Name, eListener.SSLClientAuth, serverPasses[eListener.Name], log) + } + } + for _, iListener := range l.InternalListeners { if iListener.UsedForInnerBrokerCommunication { if interBrokerListenerName == "" { @@ -291,16 +289,6 @@ func generateListenerSpecificConfig(l *v1beta1.ListenersConfig, serverPasses map } } - for _, eListener := range l.ExternalListeners { - upperedListenerType := eListener.Type.ToUpperString() - upperedListenerName := strings.ToUpper(eListener.Name) - securityProtocolMapConfig = append(securityProtocolMapConfig, fmt.Sprintf("%s:%s", upperedListenerName, upperedListenerType)) - listenerConfig = append(listenerConfig, fmt.Sprintf("%s://:%d", upperedListenerName, eListener.ContainerPort)) - // Add external listeners SSL configuration - if eListener.Type == v1beta1.SecurityProtocolSSL { - generateListenerSSLConfig(config, eListener.Name, eListener.SSLClientAuth, serverPasses[eListener.Name], log) - } - } if err := config.Set(kafkautils.KafkaConfigListenerSecurityProtocolMap, securityProtocolMapConfig); err != nil { log.Error(err, fmt.Sprintf("setting '%s' parameter in broker configuration resulted an error", kafkautils.KafkaConfigListenerSecurityProtocolMap)) } diff --git a/pkg/resources/kafka/configmap_test.go b/pkg/resources/kafka/configmap_test.go index 671a352d0..cd3405b82 100644 --- a/pkg/resources/kafka/configmap_test.go +++ b/pkg/resources/kafka/configmap_test.go @@ -615,7 +615,6 @@ zookeeper.connect=example.zk:2181/`, t.Run(test.testName, func(t *testing.T) { mockClient := mocks.NewMockClient(mockCtrl) - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) r := Reconciler{ Reconciler: resources.Reconciler{ Client: mockClient, @@ -640,9 +639,9 @@ zookeeper.connect=example.zk:2181/`, ServerSSLCertSecret: &v1.LocalObjectReference{ Name: "server-secret", }, - SSLClientAuth: test.sslClientAuth, + SSLClientAuth: test.sslClientAuth, + UsedForInnerBrokerCommunication: true, }, - UsedForInnerBrokerCommunication: true, }, }, }, diff --git a/pkg/resources/kafka/configs.go b/pkg/resources/kafka/configs.go index 9af836ed9..1653a15cb 100644 --- a/pkg/resources/kafka/configs.go +++ b/pkg/resources/kafka/configs.go @@ -18,7 +18,7 @@ import ( "strconv" "emperror.dev/errors" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" diff --git a/pkg/resources/kafka/configs_test.go b/pkg/resources/kafka/configs_test.go index a1233c976..7b30daef1 100644 --- a/pkg/resources/kafka/configs_test.go +++ b/pkg/resources/kafka/configs_test.go @@ -17,7 +17,7 @@ package kafka import ( "testing" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" properties "github.com/banzaicloud/koperator/properties/pkg" ) diff --git a/pkg/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index a76f196e3..d1fe03e4d 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -18,23 +18,21 @@ import ( "context" "fmt" "reflect" + "regexp" "sort" "strconv" "strings" "emperror.dev/errors" - ccTypes "github.com/banzaicloud/go-cruise-control/pkg/types" "github.com/go-logr/logr" - "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" - properties "github.com/banzaicloud/koperator/properties/pkg" - apiutil "github.com/banzaicloud/koperator/api/util" "github.com/banzaicloud/k8s-objectmatcher/patch" @@ -91,13 +89,24 @@ const ( nonControllerBrokerReconcilePriority // controllerBrokerReconcilePriority the priority used for controller broker used to define its priority in the reconciliation order controllerBrokerReconcilePriority + + // defaultConcurrentBrokerRestartsAllowed the default number of brokers that can be restarted in parallel + defaultConcurrentBrokerRestartsAllowed = 1 +) + +var ( + // kafkaConfigBrokerRackRegex the regex to parse the "broker.rack" Kafka property used in read-only configs + kafkaConfigBrokerRackRegex = regexp.MustCompile(`broker\.rack\s*=\s*([\w-]+)`) ) // Reconciler implements the Component Reconciler type Reconciler struct { resources.Reconciler - kafkaClientProvider kafkaclient.Provider - CruiseControlScalerFactory func(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster) (scale.CruiseControlScaler, error) + // kafkaClientProvider is used to create a new KafkaClient + kafkaClientProvider kafkaclient.Provider + // kafkaBrokerAvailabilityZoneMap is a map of broker id to availability zone used in concurrent broker restarts logic + kafkaBrokerAvailabilityZoneMap map[int32]string + CruiseControlScalerFactory func(ctx context.Context, kafkaCluster *banzaiv1beta1.KafkaCluster) (scale.CruiseControlScaler, error) } // New creates a new reconciler for Kafka @@ -108,20 +117,17 @@ func New(client client.Client, directClient client.Reader, cluster *v1beta1.Kafk DirectClient: directClient, KafkaCluster: cluster, }, - kafkaClientProvider: kafkaClientProvider, - CruiseControlScalerFactory: scale.ScaleFactoryFn(), + kafkaClientProvider: kafkaClientProvider, + kafkaBrokerAvailabilityZoneMap: getBrokerAzMap(cluster), } } func getBrokerAzMap(cluster *v1beta1.KafkaCluster) map[int32]string { brokerAzMap := make(map[int32]string) for _, broker := range cluster.Spec.Brokers { - readOnlyConfigs, err := properties.NewFromString(broker.ReadOnlyConfig) - if err == nil { - brokerRack, brokerRackConfigFound := readOnlyConfigs.Get("broker.rack") - if brokerRackConfigFound { - brokerAzMap[broker.Id] = brokerRack.Value() - } + brokerRack := getBrokerRack(broker.ReadOnlyConfig) + if brokerRack != "" { + brokerAzMap[broker.Id] = brokerRack } } // if incomplete broker AZ information, consider all brokers as being in different AZs @@ -133,6 +139,17 @@ func getBrokerAzMap(cluster *v1beta1.KafkaCluster) map[int32]string { return brokerAzMap } +func getBrokerRack(readOnlyConfig string) string { + if readOnlyConfig == "" { + return "" + } + match := kafkaConfigBrokerRackRegex.FindStringSubmatch(readOnlyConfig) + if len(match) == 2 { + return match[1] + } + return "" +} + func getCreatedPvcForBroker( ctx context.Context, c client.Reader, @@ -204,6 +221,8 @@ func (r *Reconciler) Reconcile(log logr.Logger) error { log.V(1).Info("Reconciling") + log.Info("broker rack map", "kafkaBrokerAvailabilityZoneMap", r.kafkaBrokerAvailabilityZoneMap) + ctx := context.Background() if err := k8sutil.UpdateBrokerConfigurationBackup(r.Client, r.KafkaCluster); err != nil { log.Error(err, "failed to update broker configuration backup") @@ -247,7 +266,7 @@ func (r *Reconciler) Reconcile(log logr.Logger) error { if err != nil { return errors.WrapIf(err, "could not update status for external listeners") } - intListenerStatuses, controllerIntListenerStatuses := k8sutil.CreateInternalListenerStatuses(r.KafkaCluster) + intListenerStatuses, controllerIntListenerStatuses := k8sutil.CreateInternalListenerStatuses(r.KafkaCluster, extListenerStatuses) err = k8sutil.UpdateListenerStatuses(ctx, r.Client, r.KafkaCluster, intListenerStatuses, extListenerStatuses) if err != nil { return errors.WrapIf(err, "failed to update listener statuses") @@ -575,7 +594,7 @@ func (r *Reconciler) reconcileKafkaPodDelete(ctx context.Context, log logr.Logge log.V(1).Info("pvc for broker deleted", "pvc name", volume.PersistentVolumeClaim.ClaimName, v1beta1.BrokerIdLabelKey, broker.Labels[v1beta1.BrokerIdLabelKey]) } } - err = k8sutil.DeleteStatus(r.Client, broker.Labels[v1beta1.BrokerIdLabelKey], r.KafkaCluster, log) + err = k8sutil.DeleteBrokerStatus(r.Client, broker.Labels[v1beta1.BrokerIdLabelKey], r.KafkaCluster, log) if err != nil { return errors.WrapIfWithDetails(err, "could not delete status for broker", "id", broker.Labels[v1beta1.BrokerIdLabelKey]) } @@ -861,11 +880,13 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo } desiredPod.Spec.Tolerations = uniqueTolerations } - // Check if the resource actually updated + // Check if the resource actually updated or if labels match TaintedBrokersSelector patchResult, err := patch.DefaultPatchMaker.Calculate(currentPod, desiredPod) switch { case err != nil: log.Error(err, "could not match objects", "kind", desiredType) + case r.isPodTainted(log, currentPod): + log.Info("pod has tainted labels, deleting it", "pod", currentPod) case patchResult.IsEmpty(): if !k8sutil.IsPodContainsTerminatedContainer(currentPod) && r.KafkaCluster.Status.BrokersState[currentPod.Labels[v1beta1.BrokerIdLabelKey]].ConfigurationState == v1beta1.ConfigInSync && @@ -901,25 +922,21 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo if err != nil { return errors.WrapIf(err, "failed to reconcile resource") } - // Check that all pods are present as in spec, before checking for terminating or pending pods, as we can have absent pods if len(podList.Items) < len(r.KafkaCluster.Spec.Brokers) { return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New("pod count differs from brokers spec"), "rolling upgrade in progress") } // Check if we support multiple broker restarts and restart only in same AZ, otherwise restart only 1 broker at once + concurrentBrokerRestartsAllowed := r.getConcurrentBrokerRestartsAllowed() terminatingOrPendingPods := getPodsInTerminatingOrPendingState(podList.Items) - if len(terminatingOrPendingPods) >= r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack { - return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New(strconv.Itoa(r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack)+" pod(s) is still terminating or creating"), "rolling upgrade in progress") + if len(terminatingOrPendingPods) > 0 { + log.Info("terminating or pending pods", "terminatingOrPendingPods", terminatingOrPendingPods) } - if r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack > 1 && len(terminatingOrPendingPods) > 0 { - err = r.checkCCRackAwareDistributionGoal() - if err != nil { - return err - } + if len(terminatingOrPendingPods) >= concurrentBrokerRestartsAllowed { + return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New(strconv.Itoa(concurrentBrokerRestartsAllowed)+" pod(s) is still terminating or creating"), "rolling upgrade in progress") } - kafkaBrokerAvailabilityZoneMap := getBrokerAzMap(r.KafkaCluster) - currentPodAz, _ := r.getBrokerAz(currentPod, kafkaBrokerAvailabilityZoneMap) - if r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack > 1 && r.existsTerminatingPodFromAnotherAz(currentPodAz, terminatingOrPendingPods, kafkaBrokerAvailabilityZoneMap) { + currentPodAz := r.getBrokerAz(currentPod) + if concurrentBrokerRestartsAllowed > 1 && r.existsTerminatingPodFromAnotherAz(currentPodAz, terminatingOrPendingPods) { return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New("pod is still terminating or creating from another AZ"), "rolling upgrade in progress") } @@ -957,8 +974,8 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo } // If multiple concurrent restarts and broker failures allowed, restart only brokers from the same AZ - if r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack > 1 && r.KafkaCluster.Spec.RollingUpgradeConfig.FailureThreshold > 1 { - if r.existsFailedBrokerFromAnotherRack(currentPodAz, impactedReplicas, kafkaBrokerAvailabilityZoneMap) { + if concurrentBrokerRestartsAllowed > 1 && r.KafkaCluster.Spec.RollingUpgradeConfig.FailureThreshold > 1 { + if r.existsFailedBrokerFromAnotherRack(currentPodAz, impactedReplicas) { return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New("broker is not healthy from another AZ"), "rolling upgrade in progress") } } @@ -983,56 +1000,57 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo return nil } -func (r *Reconciler) checkCCRackAwareDistributionGoal() error { - cruiseControlURL := scale.CruiseControlURLFromKafkaCluster(r.KafkaCluster) - cc, err := r.CruiseControlScalerFactory(context.TODO(), r.KafkaCluster) - if err != nil { - return errorfactory.New(errorfactory.CruiseControlNotReady{}, err, "failed to initialize Cruise Control", "cruise control url", cruiseControlURL) - } - status, err := cc.Status(context.Background()) - if err != nil { - return errorfactory.New(errorfactory.CruiseControlNotReady{}, errors.New("failed to get status from Cruise Control"), "rolling upgrade in progress") - } - if !slices.Contains(status.State.AnalyzerState.ReadyGoals, ccTypes.RackAwareDistributionGoal) { - return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New("RackAwareDistributionGoal is not ready"), "rolling upgrade in progress") - } - for _, anomaly := range status.State.AnomalyDetectorState.RecentGoalViolations { - if slices.Contains(anomaly.FixableViolatedGoals, ccTypes.RackAwareDistributionGoal) || slices.Contains(anomaly.UnfixableViolatedGoals, ccTypes.RackAwareDistributionGoal) { - return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New("RackAwareDistributionGoal is violated"), "rolling upgrade in progress") - } - } - return nil -} - -func (r *Reconciler) existsFailedBrokerFromAnotherRack(currentPodAz string, impactedReplicas map[int32]struct{}, kafkaBrokerAvailabilityZoneMap map[int32]string) bool { +func (r *Reconciler) existsFailedBrokerFromAnotherRack(currentPodAz string, impactedReplicas map[int32]struct{}) bool { if currentPodAz == "" && len(impactedReplicas) > 0 { return true } for brokerWithFailure := range impactedReplicas { - if currentPodAz != kafkaBrokerAvailabilityZoneMap[brokerWithFailure] { + if currentPodAz != r.kafkaBrokerAvailabilityZoneMap[brokerWithFailure] { return true } } return false } -func (r *Reconciler) existsTerminatingPodFromAnotherAz(currentPodAz string, terminatingOrPendingPods []corev1.Pod, kafkaBrokerAvailabilityZoneMap map[int32]string) bool { +func (r *Reconciler) getConcurrentBrokerRestartsAllowed() int { + if r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartsAllowed > 1 { + return r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartsAllowed + } + return defaultConcurrentBrokerRestartsAllowed +} + +func (r *Reconciler) existsTerminatingPodFromAnotherAz(currentPodAz string, terminatingOrPendingPods []corev1.Pod) bool { if currentPodAz == "" && len(terminatingOrPendingPods) > 0 { return true } for _, terminatingOrPendingPod := range terminatingOrPendingPods { - terminatingOrPendingPodAz, err := r.getBrokerAz(&terminatingOrPendingPod, kafkaBrokerAvailabilityZoneMap) - if err != nil || currentPodAz != terminatingOrPendingPodAz { + if currentPodAz != r.getBrokerAz(&terminatingOrPendingPod) { return true } } return false } +// Checks for match between pod labels and TaintedBrokersSelector +func (r *Reconciler) isPodTainted(log logr.Logger, pod *corev1.Pod) bool { + selector, err := metav1.LabelSelectorAsSelector(r.KafkaCluster.Spec.TaintedBrokersSelector) + + if err != nil { + log.Error(err, "Invalid tainted brokers label selector") + return false + } + + if selector.Empty() { + return false + } + return selector.Matches(labels.Set(pod.Labels)) +} + //nolint:funlen func (r *Reconciler) reconcileKafkaPvc(ctx context.Context, log logr.Logger, brokersDesiredPvcs map[string][]*corev1.PersistentVolumeClaim) error { brokersVolumesState := make(map[string]map[string]v1beta1.VolumeState) var brokerIds []string + waitForDiskRemovalToFinish := false for brokerId, desiredPvcs := range brokersDesiredPvcs { desiredType := reflect.TypeOf(&corev1.PersistentVolumeClaim{}) @@ -1049,6 +1067,67 @@ func (r *Reconciler) reconcileKafkaPvc(ctx context.Context, log logr.Logger, bro log = log.WithValues("kind", desiredType) + err := r.Client.List(ctx, pvcList, + client.InNamespace(r.KafkaCluster.GetNamespace()), matchingLabels) + if err != nil { + return errorfactory.New(errorfactory.APIFailure{}, err, "getting resource failed", "kind", desiredType) + } + + // Handle disk removal + if len(pvcList.Items) > len(desiredPvcs) { + for _, pvc := range pvcList.Items { + foundInDesired := false + existingMountPath := pvc.Annotations["mountPath"] + + for _, desiredPvc := range desiredPvcs { + desiredMountPath := desiredPvc.Annotations["mountPath"] + + if existingMountPath == desiredMountPath { + foundInDesired = true + break + } + } + + if foundInDesired { + continue + } + + mountPathToRemove := existingMountPath + if brokerState, ok := r.KafkaCluster.Status.BrokersState[brokerId]; ok { + volumeStateStatus, found := brokerState.GracefulActionState.VolumeStates[mountPathToRemove] + if !found { + // If the state is not found, it means that the disk removal was done according to the disk removal succeeded branch + log.Info("Disk removal was completed, waiting for Rolling Upgrade to remove PVC", "brokerId", brokerId, "mountPath", mountPathToRemove) + continue + } + + // Check the volume state + ccVolumeState := volumeStateStatus.CruiseControlVolumeState + switch { + case ccVolumeState.IsDiskRemovalSucceeded(): + if err := r.Client.Delete(ctx, &pvc); err != nil { + return errorfactory.New(errorfactory.APIFailure{}, err, "deleting resource failed", "kind", desiredType) + } + log.Info("resource deleted") + err = k8sutil.DeleteVolumeStatus(r.Client, brokerId, mountPathToRemove, r.KafkaCluster, log) + if err != nil { + return errors.WrapIfWithDetails(err, "could not delete volume status for broker volume", "brokerId", brokerId, "mountPath", mountPathToRemove) + } + case ccVolumeState.IsDiskRemoval(): + log.Info("Graceful disk removal is in progress", "brokerId", brokerId, "mountPath", mountPathToRemove) + waitForDiskRemovalToFinish = true + case ccVolumeState.IsDiskRebalance(): + log.Info("Graceful disk rebalance is in progress, waiting to mark disk for removal", "brokerId", brokerId, "mountPath", mountPathToRemove) + waitForDiskRemovalToFinish = true + default: + brokerVolumesState[mountPathToRemove] = v1beta1.VolumeState{CruiseControlVolumeState: v1beta1.GracefulDiskRemovalRequired} + log.Info("Marked the volume for removal", "brokerId", brokerId, "mountPath", mountPathToRemove) + waitForDiskRemovalToFinish = true + } + } + } + } + for _, desiredPvc := range desiredPvcs { currentPvc := desiredPvc.DeepCopy() log.V(1).Info("searching with label because name is empty") @@ -1079,8 +1158,10 @@ func (r *Reconciler) reconcileKafkaPvc(ctx context.Context, log logr.Logger, bro alreadyCreated = true // Checking pvc state, if bounded, so the broker has already restarted and the CC GracefulDiskRebalance has not happened yet, // then we make it happening with status update. - if _, ok := r.KafkaCluster.Status.BrokersState[brokerId].GracefulActionState.VolumeStates[mountPath]; !ok && - currentPvc.Status.Phase == corev1.ClaimBound { + // If disk removal was set, and the disk was added back, we also need to mark the volume for rebalance + volumeState, found := r.KafkaCluster.Status.BrokersState[brokerId].GracefulActionState.VolumeStates[mountPath] + if currentPvc.Status.Phase == corev1.ClaimBound && + (!found || volumeState.CruiseControlVolumeState.IsDiskRemoval()) { brokerVolumesState[mountPath] = v1beta1.VolumeState{CruiseControlVolumeState: v1beta1.GracefulDiskRebalanceRequired} } break @@ -1135,6 +1216,10 @@ func (r *Reconciler) reconcileKafkaPvc(ctx context.Context, log logr.Logger, bro } } + if waitForDiskRemovalToFinish { + return errorfactory.New(errorfactory.CruiseControlTaskRunning{}, errors.New("Disk removal pending"), "Disk removal pending") + } + return nil } @@ -1148,10 +1233,10 @@ func GetBrokersWithPendingOrRunningCCTask(kafkaCluster *v1beta1.KafkaCluster) [] (state.GracefulActionState.CruiseControlOperationReference != nil && state.GracefulActionState.CruiseControlState.IsRunningState()) { brokerIDs = append(brokerIDs, kafkaCluster.Spec.Brokers[i].Id) } else { - // Check if the volumes are rebalancing + // Check if the volumes are rebalancing or removing for _, volumeState := range state.GracefulActionState.VolumeStates { - if volumeState.CruiseControlVolumeState == v1beta1.GracefulDiskRebalanceRequired || - (volumeState.CruiseControlOperationReference != nil && volumeState.CruiseControlVolumeState.IsRunningState()) { + ccVolumeState := volumeState.CruiseControlVolumeState + if ccVolumeState.IsDiskRemoval() || ccVolumeState.IsDiskRebalance() { brokerIDs = append(brokerIDs, kafkaCluster.Spec.Brokers[i].Id) } } @@ -1165,9 +1250,9 @@ func isDesiredStorageValueInvalid(desired, current *corev1.PersistentVolumeClaim return desired.Spec.Resources.Requests.Storage().Value() < current.Spec.Resources.Requests.Storage().Value() } -func (r *Reconciler) getBrokerHost(log logr.Logger, defaultHost string, broker v1beta1.Broker, eListener v1beta1.ExternalListenerConfig) (string, error) { +func (r *Reconciler) getBrokerHost(log logr.Logger, defaultHost string, broker v1beta1.Broker, eListener v1beta1.ExternalListenerConfig, iConfig v1beta1.IngressConfig) (string, error) { brokerHost := defaultHost - portNumber := eListener.ExternalStartingPort + broker.Id + portNumber := eListener.GetBrokerPort(broker.Id) if eListener.GetAccessMethod() != corev1.ServiceTypeLoadBalancer { bConfig, err := broker.GetBrokerConfig(r.KafkaCluster.Spec) @@ -1201,6 +1286,12 @@ func (r *Reconciler) getBrokerHost(log logr.Logger, defaultHost string, broker v brokerHost = fmt.Sprintf("%s-%d-%s.%s%s", r.KafkaCluster.Name, broker.Id, eListener.Name, r.KafkaCluster.Namespace, brokerHost) } } + if eListener.TLSEnabled() { + brokerHost = iConfig.EnvoyConfig.GetBrokerHostname(broker.Id) + if brokerHost == "" { + return "", errors.New("brokerHostnameTemplate is not set in the ingress service settings") + } + } return fmt.Sprintf("%s:%d", brokerHost, portNumber), nil } @@ -1269,7 +1360,7 @@ func (r *Reconciler) createExternalListenerStatuses(log logr.Logger) (map[string } for _, broker := range r.KafkaCluster.Spec.Brokers { - brokerHostPort, err := r.getBrokerHost(log, host, broker, eListener) + brokerHostPort, err := r.getBrokerHost(log, host, broker, eListener, iConfig) if err != nil { return nil, errors.WrapIfWithDetails(err, "could not get brokerHost for external listener status", "brokerID", broker.Id) } @@ -1392,12 +1483,12 @@ func getPodsInTerminatingOrPendingState(items []corev1.Pod) []corev1.Pod { return pods } -func (r *Reconciler) getBrokerAz(pod *corev1.Pod, kafkaBrokerAvailabilityZoneMap map[int32]string) (string, error) { +func (r *Reconciler) getBrokerAz(pod *corev1.Pod) string { brokerId, err := strconv.ParseInt(pod.Labels[v1beta1.BrokerIdLabelKey], 10, 32) if err != nil { - return "", err + return "" } - return kafkaBrokerAvailabilityZoneMap[int32(brokerId)], nil + return r.kafkaBrokerAvailabilityZoneMap[int32(brokerId)] } func getServiceFromExternalListener(client client.Client, cluster *v1beta1.KafkaCluster, diff --git a/pkg/resources/kafka/kafka_test.go b/pkg/resources/kafka/kafka_test.go index 0aba87a46..e6c891f15 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -21,7 +21,6 @@ import ( "time" "emperror.dev/errors" - ccTypes "github.com/banzaicloud/go-cruise-control/pkg/types" "github.com/go-logr/logr" "github.com/onsi/gomega" "github.com/stretchr/testify/assert" @@ -29,8 +28,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" - "github.com/banzaicloud/koperator/pkg/scale" - "github.com/banzaicloud/koperator/pkg/kafkaclient" corev1 "k8s.io/api/core/v1" @@ -39,9 +36,8 @@ import ( "github.com/banzaicloud/koperator/api/v1alpha1" "github.com/banzaicloud/koperator/api/v1beta1" - controllerMocks "github.com/banzaicloud/koperator/controllers/tests/mocks" "github.com/banzaicloud/koperator/pkg/resources" - mocks "github.com/banzaicloud/koperator/pkg/resources/kafka/mocks" + "github.com/banzaicloud/koperator/pkg/resources/kafka/mocks" ) func TestGetBrokersWithPendingOrRunningCCTask(t *testing.T) { @@ -603,11 +599,11 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen }, internalListeners: []v1beta1.InternalListenerConfig{{ CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_auto", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_auto", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -643,11 +639,11 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen }, internalListeners: []v1beta1.InternalListenerConfig{{ CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_auto", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_auto", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -726,27 +722,27 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen internalListeners: []v1beta1.InternalListenerConfig{ { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_auto_1", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_auto_1", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_auto_2", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_auto_2", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_auto_3", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_auto_3", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ @@ -756,8 +752,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -819,8 +815,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ @@ -830,8 +826,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -851,11 +847,11 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen internalListeners: []v1beta1.InternalListenerConfig{ { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: v1beta1.SecurityProtocol("ssl"), - Name: "internal_custom_1", - ContainerPort: 9092, + Type: v1beta1.SecurityProtocol("ssl"), + Name: "internal_custom_1", + ContainerPort: 9092, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ @@ -865,8 +861,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, }, @@ -959,6 +955,275 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen } } +func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { + t.Parallel() + testCases := []struct { + testName string + brokersDesiredPvcs map[string][]*corev1.PersistentVolumeClaim + existingPvcs []*corev1.PersistentVolumeClaim + kafkaClusterSpec v1beta1.KafkaClusterSpec + kafkaClusterStatus v1beta1.KafkaClusterStatus + expectedError bool + expectedDeletePvc bool + expectedVolumeState map[string]v1beta1.CruiseControlVolumeState + }{ + { + testName: "If no disk removed, do nothing", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{}, + expectedError: false, + expectedDeletePvc: false, + expectedVolumeState: nil, + }, + { + testName: "If disk removed, mark it as GracefulDiskRemovalRequired and return error", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{ + BrokersState: map[string]v1beta1.BrokerState{ + "0": { + GracefulActionState: v1beta1.GracefulActionState{ + VolumeStates: map[string]v1beta1.VolumeState{ + "/path/to/mount2": { + CruiseControlVolumeState: v1beta1.GracefulDiskRebalanceSucceeded, + }, + }, + }, + }, + }, + }, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRemovalRequired, + }, + }, + { + testName: "If disk is rebalancing, wait for it to finish", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{ + BrokersState: map[string]v1beta1.BrokerState{ + "0": { + GracefulActionState: v1beta1.GracefulActionState{ + VolumeStates: map[string]v1beta1.VolumeState{ + "/path/to/mount2": { + CruiseControlVolumeState: v1beta1.GracefulDiskRebalanceScheduled, + }, + }, + }, + }, + }, + }, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRebalanceScheduled, + }, + }, + { + testName: "Wait for disk removal to finish", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{ + BrokersState: map[string]v1beta1.BrokerState{ + "0": { + GracefulActionState: v1beta1.GracefulActionState{ + VolumeStates: map[string]v1beta1.VolumeState{ + "/path/to/mount2": { + CruiseControlVolumeState: v1beta1.GracefulDiskRemovalRunning, + }, + }, + }, + }, + }, + }, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRemovalRunning, + }, + }, + { + testName: "If disk removal successful, do not return error and delete pvc and volume state", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{ + BrokersState: map[string]v1beta1.BrokerState{ + "0": { + GracefulActionState: v1beta1.GracefulActionState{ + VolumeStates: map[string]v1beta1.VolumeState{ + "/path/to/mount2": { + CruiseControlVolumeState: v1beta1.GracefulDiskRemovalSucceeded, + }, + }, + }, + }, + }, + }, + expectedError: false, + expectedDeletePvc: true, + expectedVolumeState: nil, + }, + { + testName: "If disk removal failed, and it is readded, mark the disk as rebalancing", + brokersDesiredPvcs: map[string][]*corev1.PersistentVolumeClaim{ + "0": { + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + }, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), + }, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{ + BrokersState: map[string]v1beta1.BrokerState{ + "0": { + GracefulActionState: v1beta1.GracefulActionState{ + VolumeStates: map[string]v1beta1.VolumeState{ + "/path/to/mount2": { + CruiseControlVolumeState: v1beta1.GracefulDiskRemovalCompletedWithError, + }, + }, + }, + }, + }, + }, + expectedError: false, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRebalanceRequired, + }, + }, + } + + mockCtrl := gomock.NewController(t) + + for _, test := range testCases { + mockClient := mocks.NewMockClient(mockCtrl) + mockSubResourceClient := mocks.NewMockSubResourceClient(mockCtrl) + t.Run(test.testName, func(t *testing.T) { + r := Reconciler{ + Reconciler: resources.Reconciler{ + Client: mockClient, + KafkaCluster: &v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + }, + }, + } + + // Set up the mockClient to return the provided test.existingPvcs + mockClient.EXPECT().List( + context.TODO(), + gomock.AssignableToTypeOf(&corev1.PersistentVolumeClaimList{}), + client.InNamespace("kafka"), + gomock.Any(), + ).Do(func(ctx context.Context, list *corev1.PersistentVolumeClaimList, opts ...client.ListOption) { + // Convert []*corev1.PersistentVolumeClaim to []corev1.PersistentVolumeClaim + pvcItems := make([]corev1.PersistentVolumeClaim, len(test.existingPvcs)) + for i, pvc := range test.existingPvcs { + pvcItems[i] = *pvc + } + + list.Items = pvcItems + }).Return(nil).AnyTimes() + + // Mock the client.Delete call + if test.expectedDeletePvc { + mockClient.EXPECT().Delete(context.TODO(), gomock.AssignableToTypeOf(&corev1.PersistentVolumeClaim{})).Return(nil) + } + + // Mock the status update call + mockClient.EXPECT().Status().Return(mockSubResourceClient).AnyTimes() + mockSubResourceClient.EXPECT().Update(context.Background(), gomock.AssignableToTypeOf(&v1beta1.KafkaCluster{})).Do(func(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster, opts ...client.SubResourceUpdateOption) { + r.KafkaCluster.Status = kafkaCluster.Status + }).Return(nil).AnyTimes() + + // Set up the r.KafkaCluster.Status with the provided test.kafkaClusterStatus + r.KafkaCluster.Status = test.kafkaClusterStatus + + // Call the reconcileKafkaPvc function with the provided test.brokersDesiredPvcs + err := r.reconcileKafkaPvc(context.TODO(), logf.Log, test.brokersDesiredPvcs) + + // Test that the expected error is returned + if test.expectedError { + assert.NotNil(t, err, "Expected an error but got nil") + } else { + assert.Nil(t, err, "Expected no error but got an error") + } + + // Test that the expected volume state is set + brokerState := r.KafkaCluster.Status.BrokersState["0"] + if test.expectedVolumeState != nil { + for mountPath, expectedState := range test.expectedVolumeState { + actualState, exists := brokerState.GracefulActionState.VolumeStates[mountPath] + assert.True(t, exists, "Expected volume state not found for mount path %s", mountPath) + assert.Equal(t, expectedState, actualState.CruiseControlVolumeState, "Volume state mismatch for mount path %s", mountPath) + } + } + }) + } +} + +//nolint:unparam +func createPvc(name, brokerId, mountPath string) *corev1.PersistentVolumeClaim { + return &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + v1beta1.BrokerIdLabelKey: brokerId, + }, + Annotations: map[string]string{ + "mountPath": mountPath, + }, + }, + Status: corev1.PersistentVolumeClaimStatus{ + Phase: corev1.ClaimBound, + }, + } +} + // nolint funlen func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { t.Parallel() @@ -970,7 +1235,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { pods []corev1.Pod allOfflineReplicas []int32 outOfSyncReplicas []int32 - ccStatus *scale.StatusTaskResult errorExpected bool }{ { @@ -1005,9 +1269,9 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { desiredPod: &corev1.Pod{}, currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201"}}, pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201"}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, errorExpected: true, }, @@ -1021,7 +1285,7 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { Spec: v1beta1.KafkaClusterSpec{ Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - ConcurrentBrokerRestartCountPerRack: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1029,9 +1293,9 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { desiredPod: &corev1.Pod{}, currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-301"}}, pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301"}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, errorExpected: true, }, @@ -1045,7 +1309,7 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { Spec: v1beta1.KafkaClusterSpec{ Brokers: []v1beta1.Broker{{Id: 101}, {Id: 102}, {Id: 201}, {Id: 102}, {Id: 301}, {Id: 302}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - ConcurrentBrokerRestartCountPerRack: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1060,14 +1324,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, errorExpected: true, }, { @@ -1086,7 +1342,7 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, {Id: 302, ReadOnlyConfig: ""}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - ConcurrentBrokerRestartCountPerRack: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1101,14 +1357,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, errorExpected: true, }, { @@ -1142,10 +1390,12 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - errorExpected: true, + outOfSyncReplicas: []int32{101}, + allOfflineReplicas: []int32{}, + errorExpected: true, }, { - testName: "Pod is deleted if allowed concurrent restarts is default and failure threshold is not reached", + testName: "Pod is deleted if allowed concurrent restarts is not specified and failure threshold is not reached", kafkaCluster: v1beta1.KafkaCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "kafka", @@ -1160,8 +1410,7 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, {Id: 302, ReadOnlyConfig: "broker.rack=az3"}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 1, - ConcurrentBrokerRestartCountPerRack: 1, + FailureThreshold: 1, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1176,9 +1425,9 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, + errorExpected: false, allOfflineReplicas: []int32{}, outOfSyncReplicas: []int32{}, - errorExpected: false, }, { testName: "Pod is not deleted if pod is restarting in another AZ, even if allowed concurrent restarts is not reached", @@ -1196,8 +1445,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, {Id: 302, ReadOnlyConfig: "broker.rack=az3"}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1212,14 +1461,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, errorExpected: true, }, { @@ -1238,8 +1479,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, {Id: 302, ReadOnlyConfig: "broker.rack=az3"}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1254,45 +1495,9 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - allOfflineReplicas: []int32{}, outOfSyncReplicas: []int32{201}, - errorExpected: true, - }, - { - testName: "Pod is deleted if all pods are running and CC RackAwareDistributionGoal is not ready and allowed concurrent restarts is not reached", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 102, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 202, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, - {Id: 302, ReadOnlyConfig: "broker.rack=az3"}}, - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, - }, - }, - Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, - }, - desiredPod: &corev1.Pod{}, - currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-102", Labels: map[string]string{"brokerId": "102"}}}, - pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-102", Labels: map[string]string{"brokerId": "102"}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-202", Labels: map[string]string{"brokerId": "202"}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, - }, allOfflineReplicas: []int32{}, - outOfSyncReplicas: []int32{101}, - errorExpected: false, + errorExpected: true, }, { testName: "Pod is deleted if failure is in same AZ and allowed concurrent restarts is not reached", @@ -1310,8 +1515,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, {Id: 302, ReadOnlyConfig: "broker.rack=az3"}}, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1326,17 +1531,9 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-302", Labels: map[string]string{"brokerId": "302"}}}, }, - allOfflineReplicas: []int32{}, outOfSyncReplicas: []int32{101}, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, - errorExpected: false, + allOfflineReplicas: []int32{}, + errorExpected: false, }, { testName: "Pod is not deleted if pod is restarting in another AZ, if brokers per AZ < tolerated failures", @@ -1352,8 +1549,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, }, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1365,14 +1562,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, errorExpected: true, }, { @@ -1389,8 +1578,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, }, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1402,8 +1591,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, - allOfflineReplicas: []int32{}, outOfSyncReplicas: []int32{101}, + allOfflineReplicas: []int32{}, errorExpected: true, }, { @@ -1420,8 +1609,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, }, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1451,8 +1640,8 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {Id: 301, ReadOnlyConfig: "broker.rack=az-3"}, }, RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, }, }, Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, @@ -1464,14 +1653,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, - ccStatus: &scale.StatusTaskResult{ - State: &ccTypes.StateResult{ - AnalyzerState: ccTypes.AnalyzerState{ReadyGoals: []ccTypes.Goal{ccTypes.RackAwareDistributionGoal}}, - AnomalyDetectorState: ccTypes.AnomalyDetectorState{ - RecentGoalViolations: []ccTypes.AnomalyDetails{{UnfixableViolatedGoals: []ccTypes.Goal{}, FixableViolatedGoals: []ccTypes.Goal{}}}, - }, - }, - }, errorExpected: true, }, } @@ -1508,13 +1689,6 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { } mockKafkaClientProvider.On("NewFromCluster", mockClient, &test.kafkaCluster).Return(mockedKafkaClient, func() {}, nil) - // Mock Cruise Control client - mockCruiseControl := controllerMocks.NewMockCruiseControlScaler(mockCtrl) - if test.ccStatus != nil { - mockCruiseControl.EXPECT().Status(context.Background()).Return(*test.ccStatus, nil) - } - r.CruiseControlScalerFactory = controllerMocks.NewMockScaleFactory(mockCruiseControl) - // Call the handleRollingUpgrade function with the provided test.desiredPod and test.currentPod err := r.handleRollingUpgrade(logf.Log, test.desiredPod, test.currentPod, reflect.TypeOf(test.desiredPod)) @@ -1527,85 +1701,3 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { }) } } - -func TestGetBrokerAzMap(t *testing.T) { - t.Parallel() - testCases := []struct { - testName string - kafkaCluster v1beta1.KafkaCluster - expectedAzMap map[int32]string - }{ - { - testName: "Brokers have different AZs if no broker rack value is set", - kafkaCluster: v1beta1.KafkaCluster{ - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: ""}, - {Id: 201, ReadOnlyConfig: ""}, - {Id: 301, ReadOnlyConfig: ""}, - }, - }, - }, - expectedAzMap: map[int32]string{101: "101", 201: "201", 301: "301"}, - }, - { - testName: "Brokers have different AZs if one broker has no broker rack value set", - kafkaCluster: v1beta1.KafkaCluster{ - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 102, ReadOnlyConfig: ""}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 202, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, - {Id: 302, ReadOnlyConfig: "broker.rack=az3"}, - }, - }, - }, - expectedAzMap: map[int32]string{101: "101", 102: "102", 201: "201", 202: "202", 301: "301", 302: "302"}, - }, - { - testName: "Brokers have different AZs if read only configs is a corrupted string for one broker", - kafkaCluster: v1beta1.KafkaCluster{ - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack;az1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, - }, - }, - }, - expectedAzMap: map[int32]string{101: "101", 201: "201", 301: "301"}, - }, - { - testName: "Brokers have correct AZs if read only configs is valid for all brokers", - kafkaCluster: v1beta1.KafkaCluster{ - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az-1"}, - {Id: 102, ReadOnlyConfig: "broker.rack=az-1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az-2"}, - {Id: 202, ReadOnlyConfig: "broker.rack=az-2"}, - {Id: 301, ReadOnlyConfig: "broker.rack=az-3"}, - {Id: 302, ReadOnlyConfig: "broker.rack=az-3"}, - }, - }, - }, - expectedAzMap: map[int32]string{ - 101: "az-1", - 102: "az-1", - 201: "az-2", - 202: "az-2", - 301: "az-3", - 302: "az-3", - }, - }, - } - - for _, test := range testCases { - t.Run(test.testName, func(t *testing.T) { - azMap := getBrokerAzMap(&test.kafkaCluster) - assert.Equal(t, test.expectedAzMap, azMap) - }) - } -} diff --git a/pkg/resources/kafka/mocks/Client.go b/pkg/resources/kafka/mocks/Client.go index dbd94b018..0a0ceab77 100644 --- a/pkg/resources/kafka/mocks/Client.go +++ b/pkg/resources/kafka/mocks/Client.go @@ -26,6 +26,7 @@ import ( gomock "go.uber.org/mock/gomock" meta "k8s.io/apimachinery/pkg/api/meta" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" types "k8s.io/apimachinery/pkg/types" client "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -129,6 +130,36 @@ func (mr *MockClientMockRecorder) Get(arg0, arg1, arg2 interface{}, arg3 ...inte return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockClient)(nil).Get), varargs...) } +// GroupVersionKindFor mocks base method. +func (m *MockClient) GroupVersionKindFor(arg0 runtime.Object) (schema.GroupVersionKind, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GroupVersionKindFor", arg0) + ret0, _ := ret[0].(schema.GroupVersionKind) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GroupVersionKindFor indicates an expected call of GroupVersionKindFor. +func (mr *MockClientMockRecorder) GroupVersionKindFor(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GroupVersionKindFor", reflect.TypeOf((*MockClient)(nil).GroupVersionKindFor), arg0) +} + +// IsObjectNamespaced mocks base method. +func (m *MockClient) IsObjectNamespaced(arg0 runtime.Object) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsObjectNamespaced", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsObjectNamespaced indicates an expected call of IsObjectNamespaced. +func (mr *MockClientMockRecorder) IsObjectNamespaced(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsObjectNamespaced", reflect.TypeOf((*MockClient)(nil).IsObjectNamespaced), arg0) +} + // List mocks base method. func (m *MockClient) List(arg0 context.Context, arg1 client.ObjectList, arg2 ...client.ListOption) error { m.ctrl.T.Helper() diff --git a/pkg/resources/kafka/mocks/KafkaClient.go b/pkg/resources/kafka/mocks/KafkaClient.go index 3669ce70b..22fcead30 100644 --- a/pkg/resources/kafka/mocks/KafkaClient.go +++ b/pkg/resources/kafka/mocks/KafkaClient.go @@ -22,7 +22,7 @@ package mocks import ( reflect "reflect" - sarama "github.com/Shopify/sarama" + sarama "github.com/IBM/sarama" v1alpha1 "github.com/banzaicloud/koperator/api/v1alpha1" kafkaclient "github.com/banzaicloud/koperator/pkg/kafkaclient" gomock "go.uber.org/mock/gomock" diff --git a/pkg/resources/kafka/mocks/SubResourceClient.go b/pkg/resources/kafka/mocks/SubResourceClient.go new file mode 100644 index 000000000..5df166e24 --- /dev/null +++ b/pkg/resources/kafka/mocks/SubResourceClient.go @@ -0,0 +1,123 @@ +// Copyright Š 2023 Cisco Systems, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mocks + +import ( + "context" + "reflect" + + "go.uber.org/mock/gomock" + + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// MockSubResourceClient is a mock of SubResourceClient interface. +type MockSubResourceClient struct { + ctrl *gomock.Controller + recorder *MockSubResourceClientMockRecorder +} + +// MockSubResourceClientMockRecorder is the mock recorder for MockSubResourceClient. +type MockSubResourceClientMockRecorder struct { + mock *MockSubResourceClient +} + +// NewMockSubResourceClient creates a new mock instance. +func NewMockSubResourceClient(ctrl *gomock.Controller) *MockSubResourceClient { + mock := &MockSubResourceClient{ctrl: ctrl} + mock.recorder = &MockSubResourceClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSubResourceClient) EXPECT() *MockSubResourceClientMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockSubResourceClient) Create(arg0 context.Context, arg1, arg2 client.Object, arg3 ...client.SubResourceCreateOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2} + for _, a := range arg3 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Create", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockSubResourceClientMockRecorder) Create(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockSubResourceClient)(nil).Create), varargs...) +} + +// Get mocks base method. +func (m *MockSubResourceClient) Get(arg0 context.Context, arg1, arg2 client.Object, arg3 ...client.SubResourceGetOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2} + for _, a := range arg3 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Get", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Get indicates an expected call of Get. +func (mr *MockSubResourceClientMockRecorder) Get(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockSubResourceClient)(nil).Get), varargs...) +} + +// Patch mocks base method. +func (m *MockSubResourceClient) Patch(arg0 context.Context, arg1 client.Object, arg2 client.Patch, arg3 ...client.SubResourcePatchOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2} + for _, a := range arg3 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Patch", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Patch indicates an expected call of Patch. +func (mr *MockSubResourceClientMockRecorder) Patch(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Patch", reflect.TypeOf((*MockSubResourceClient)(nil).Patch), varargs...) +} + +// Update mocks base method. +func (m *MockSubResourceClient) Update(arg0 context.Context, arg1 client.Object, arg2 ...client.SubResourceUpdateOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Update", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockSubResourceClientMockRecorder) Update(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockSubResourceClient)(nil).Update), varargs...) +} diff --git a/pkg/resources/nodeportexternalaccess/service.go b/pkg/resources/nodeportexternalaccess/service.go index 3a2348db7..e35cbb1ed 100644 --- a/pkg/resources/nodeportexternalaccess/service.go +++ b/pkg/resources/nodeportexternalaccess/service.go @@ -33,7 +33,7 @@ func (r *Reconciler) service(_ logr.Logger, id int32, brokerConfig *v1beta1.BrokerConfig, extListener v1beta1.ExternalListenerConfig) runtime.Object { nodePort := int32(0) if extListener.ExternalStartingPort > 0 { - nodePort = extListener.ExternalStartingPort + id + nodePort = extListener.GetBrokerPort(id) } service := &corev1.Service{ ObjectMeta: templates.ObjectMetaWithAnnotations( diff --git a/pkg/scale/scale.go b/pkg/scale/scale.go index 90afd7ff5..cb71fd4f1 100644 --- a/pkg/scale/scale.go +++ b/pkg/scale/scale.go @@ -35,11 +35,12 @@ import ( const ( // Constants for the Cruise Control operations parameters // Check for more details: https://github.com/linkedin/cruise-control/wiki/REST-APIs - paramBrokerID = "brokerid" - paramExcludeDemoted = "exclude_recently_demoted_brokers" - paramExcludeRemoved = "exclude_recently_removed_brokers" - paramDestbrokerIDs = "destination_broker_ids" - paramRebalanceDisk = "rebalance_disk" + ParamBrokerID = "brokerid" + ParamExcludeDemoted = "exclude_recently_demoted_brokers" + ParamExcludeRemoved = "exclude_recently_removed_brokers" + ParamDestbrokerIDs = "destination_broker_ids" + ParamRebalanceDisk = "rebalance_disk" + ParamBrokerIDAndLogDirs = "brokerid_and_logdirs" // Cruise Control API returns NullPointerException when a broker storage capacity calculations are missing // from the Cruise Control configurations nullPointerExceptionErrString = "NullPointerException" @@ -50,20 +51,23 @@ const ( var ( newCruiseControlScaler = createNewDefaultCruiseControlScaler addBrokerSupportedParams = map[string]struct{}{ - paramBrokerID: {}, - paramExcludeDemoted: {}, - paramExcludeRemoved: {}, + ParamBrokerID: {}, + ParamExcludeDemoted: {}, + ParamExcludeRemoved: {}, } removeBrokerSupportedParams = map[string]struct{}{ - paramBrokerID: {}, - paramExcludeDemoted: {}, - paramExcludeRemoved: {}, + ParamBrokerID: {}, + ParamExcludeDemoted: {}, + ParamExcludeRemoved: {}, } rebalanceSupportedParams = map[string]struct{}{ - paramDestbrokerIDs: {}, - paramRebalanceDisk: {}, - paramExcludeDemoted: {}, - paramExcludeRemoved: {}, + ParamDestbrokerIDs: {}, + ParamRebalanceDisk: {}, + ParamExcludeDemoted: {}, + ParamExcludeRemoved: {}, + } + removeDisksSupportedParams = map[string]struct{}{ + ParamBrokerIDAndLogDirs: {}, } ) @@ -121,7 +125,7 @@ func (cc *cruiseControlScaler) Status(ctx context.Context) (StatusTaskResult, er StartedAt: resp.Date, ResponseStatusCode: resp.StatusCode, RequestURL: resp.RequestURL, - State: v1beta1.CruiseControlTaskInExecution, + State: v1beta1.CruiseControlTaskActive, }, }, nil } @@ -134,10 +138,9 @@ func (cc *cruiseControlScaler) Status(ctx context.Context) (StatusTaskResult, er StartedAt: resp.Date, ResponseStatusCode: resp.StatusCode, RequestURL: resp.RequestURL, - State: v1beta1.CruiseControlTaskCompleted, + State: v1beta1.CruiseControlTaskActive, }, Status: &status, - State: resp.Result, }, nil } @@ -291,19 +294,19 @@ func (cc *cruiseControlScaler) AddBrokersWithParams(ctx context.Context, params for param, pvalue := range params { if _, ok := addBrokerSupportedParams[param]; ok { switch param { - case paramBrokerID: + case ParamBrokerID: ret, err := parseBrokerIDtoSlice(pvalue) if err != nil { return nil, err } addBrokerReq.BrokerIDs = ret - case paramExcludeDemoted: + case ParamExcludeDemoted: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err } addBrokerReq.ExcludeRecentlyDemotedBrokers = ret - case paramExcludeRemoved: + case ParamExcludeRemoved: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err @@ -368,19 +371,19 @@ func (cc *cruiseControlScaler) RemoveBrokersWithParams(ctx context.Context, para for param, pvalue := range params { if _, ok := removeBrokerSupportedParams[param]; ok { switch param { - case paramBrokerID: + case ParamBrokerID: ret, err := parseBrokerIDtoSlice(pvalue) if err != nil { return nil, err } rmBrokerReq.BrokerIDs = ret - case paramExcludeDemoted: + case ParamExcludeDemoted: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err } rmBrokerReq.ExcludeRecentlyDemotedBrokers = ret - case paramExcludeRemoved: + case ParamExcludeRemoved: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err @@ -550,25 +553,25 @@ func (cc *cruiseControlScaler) RebalanceWithParams(ctx context.Context, params m for param, pvalue := range params { if _, ok := rebalanceSupportedParams[param]; ok { switch param { - case paramDestbrokerIDs: + case ParamDestbrokerIDs: ret, err := parseBrokerIDtoSlice(pvalue) if err != nil { return nil, err } rebalanceReq.DestinationBrokerIDs = ret - case paramRebalanceDisk: + case ParamRebalanceDisk: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err } rebalanceReq.RebalanceDisk = ret - case paramExcludeDemoted: + case ParamExcludeDemoted: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err } rebalanceReq.ExcludeRecentlyDemotedBrokers = ret - case paramExcludeRemoved: + case ParamExcludeRemoved: ret, err := strconv.ParseBool(pvalue) if err != nil { return nil, err @@ -602,6 +605,81 @@ func (cc *cruiseControlScaler) RebalanceWithParams(ctx context.Context, params m }, nil } +func (cc *cruiseControlScaler) RemoveDisksWithParams(ctx context.Context, params map[string]string) (*Result, error) { + removeReq := &api.RemoveDisksRequest{} + + for param, pvalue := range params { + if _, ok := removeDisksSupportedParams[param]; ok { + switch param { + case ParamBrokerIDAndLogDirs: + ret, err := parseBrokerIDsAndLogDirsToMap(pvalue) + if err != nil { + return nil, err + } + removeReq.BrokerIDAndLogDirs = ret + default: + return nil, fmt.Errorf("unsupported %s parameter: %s, supported parameters: %s", v1alpha1.OperationRemoveDisks, param, removeDisksSupportedParams) + } + } + } + + if len(removeReq.BrokerIDAndLogDirs) == 0 { + return &Result{ + State: v1beta1.CruiseControlTaskCompleted, + }, nil + } + + removeResp, err := cc.client.RemoveDisks(ctx, removeReq) + if err != nil { + return &Result{ + TaskID: removeResp.TaskID, + StartedAt: removeResp.Date, + ResponseStatusCode: removeResp.StatusCode, + RequestURL: removeResp.RequestURL, + State: v1beta1.CruiseControlTaskCompletedWithError, + Err: err, + }, err + } + + return &Result{ + TaskID: removeResp.TaskID, + StartedAt: removeResp.Date, + ResponseStatusCode: removeResp.StatusCode, + RequestURL: removeResp.RequestURL, + Result: removeResp.Result, + State: v1beta1.CruiseControlTaskActive, + }, nil +} + +func parseBrokerIDsAndLogDirsToMap(brokerIDsAndLogDirs string) (map[int32][]string, error) { + // brokerIDsAndLogDirs format: brokerID1-logDir1,brokerID2-logDir2,brokerID1-logDir3 + brokerIDLogDirMap := make(map[int32][]string) + + if len(brokerIDsAndLogDirs) == 0 { + return brokerIDLogDirMap, nil + } + + pairs := strings.Split(brokerIDsAndLogDirs, ",") + for _, pair := range pairs { + components := strings.SplitN(pair, "-", 2) + if len(components) != 2 { + return nil, errors.New("invalid format for brokerIDsAndLogDirs") + } + + brokerID, err := strconv.ParseInt(components[0], 10, 32) + if err != nil { + return nil, errors.New("invalid broker ID") + } + + logDir := components[1] + + // Add logDir to the corresponding brokerID's list + brokerIDLogDirMap[int32(brokerID)] = append(brokerIDLogDirMap[int32(brokerID)], logDir) + } + + return brokerIDLogDirMap, nil +} + func (cc *cruiseControlScaler) KafkaClusterLoad(ctx context.Context) (*api.KafkaClusterLoadResponse, error) { clusterLoadResp, err := cc.client.KafkaClusterLoad(ctx, api.KafkaClusterLoadRequestWithDefaults()) if err != nil { diff --git a/pkg/scale/scale_test.go b/pkg/scale/scale_test.go new file mode 100644 index 000000000..ccaf6ad0c --- /dev/null +++ b/pkg/scale/scale_test.go @@ -0,0 +1,70 @@ +// Copyright Š 2023 Cisco Systems, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package scale + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseBrokerIDsAndLogDirToMap(t *testing.T) { + testCases := []struct { + testName string + brokerIDsAndLogDirs string + want map[int32][]string + wantErr bool + }{ + { + testName: "valid input", + brokerIDsAndLogDirs: "102-/kafka-logs3/kafka,101-/kafka-logs3/kafka,101-/kafka-logs2/kafka", + want: map[int32][]string{ + 101: {"/kafka-logs3/kafka", "/kafka-logs2/kafka"}, + 102: {"/kafka-logs3/kafka"}, + }, + wantErr: false, + }, + { + testName: "empty input", + brokerIDsAndLogDirs: "", + want: map[int32][]string{}, + wantErr: false, + }, + { + testName: "invalid format", + brokerIDsAndLogDirs: "1-dirA,2-dirB,1", + want: nil, + wantErr: true, + }, + { + testName: "invalid broker ID", + brokerIDsAndLogDirs: "1-dirA,abc-dirB,1-dirC", + want: nil, + wantErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.testName, func(t *testing.T) { + got, err := parseBrokerIDsAndLogDirsToMap(tc.brokerIDsAndLogDirs) + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.want, got) + } + }) + } +} diff --git a/pkg/scale/types.go b/pkg/scale/types.go index 6a7c0bcbf..92b9d8f63 100644 --- a/pkg/scale/types.go +++ b/pkg/scale/types.go @@ -35,6 +35,7 @@ type CruiseControlScaler interface { RebalanceWithParams(ctx context.Context, params map[string]string) (*Result, error) StopExecution(ctx context.Context) (*Result, error) RemoveBrokers(ctx context.Context, brokerIDs ...string) (*Result, error) + RemoveDisksWithParams(ctx context.Context, params map[string]string) (*Result, error) RebalanceDisks(ctx context.Context, brokerIDs ...string) (*Result, error) BrokersWithState(ctx context.Context, states ...KafkaBrokerState) ([]string, error) KafkaClusterState(ctx context.Context) (*types.KafkaClusterState, error) @@ -64,7 +65,6 @@ const ( type StatusTaskResult struct { TaskResult *Result Status *CruiseControlStatus - State *types.StateResult } // CruiseControlStatus struct is used to describe internal state of Cruise Control. diff --git a/pkg/util/cert/certutil.go b/pkg/util/cert/certutil.go index 179047085..fe3d4c878 100644 --- a/pkg/util/cert/certutil.go +++ b/pkg/util/cert/certutil.go @@ -139,7 +139,6 @@ func DecodeCertificate(raw []byte) (cert *x509.Certificate, err error) { // GeneratePass generates a random password func GeneratePass(length int) (passw []byte) { - mathrand.Seed(time.Now().UnixNano()) var b strings.Builder for i := 0; i < length; i++ { b.WriteRune(passChars[mathrand.Intn(len(passChars))]) @@ -254,7 +253,7 @@ func GenerateTestCert() (cert, key []byte, expectedDn string, err error) { } buf := new(bytes.Buffer) if err = pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert}); err != nil { - return + return //nolint:golint,nakedret } cert = buf.Bytes() key, err = encodePrivateKeyInPemFormat(priv) diff --git a/pkg/util/client/common.go b/pkg/util/client/common.go index 9ee4c923c..360091f83 100644 --- a/pkg/util/client/common.go +++ b/pkg/util/client/common.go @@ -22,13 +22,28 @@ import ( ) func UseSSL(cluster *v1beta1.KafkaCluster) bool { - return cluster.Spec.ListenersConfig.InternalListeners[determineInternalListenerForInnerCom(cluster.Spec.ListenersConfig.InternalListeners)].Type.IsSSL() + for _, val := range cluster.Spec.ListenersConfig.InternalListeners { + if val.UsedForInnerBrokerCommunication && val.Type.IsSSL() { + return true + } + } + for _, val := range cluster.Spec.ListenersConfig.ExternalListeners { + if val.UsedForInnerBrokerCommunication && val.Type.IsSSL() { + return true + } + } + return false } -func determineInternalListenerForInnerCom(internalListeners []v1beta1.InternalListenerConfig) int { - for id, val := range internalListeners { +func getContainerPortForInnerCom(internalListeners []v1beta1.InternalListenerConfig, extListeners []v1beta1.ExternalListenerConfig) int32 { + for _, val := range internalListeners { + if val.UsedForInnerBrokerCommunication { + return val.ContainerPort + } + } + for _, val := range extListeners { if val.UsedForInnerBrokerCommunication { - return id + return val.ContainerPort } } return 0 @@ -50,6 +65,6 @@ func GenerateKafkaAddressWithoutPort(cluster *v1beta1.KafkaCluster) string { } func GenerateKafkaAddress(cluster *v1beta1.KafkaCluster) string { - return fmt.Sprintf("%s:%d", GenerateKafkaAddressWithoutPort(cluster), - cluster.Spec.ListenersConfig.InternalListeners[determineInternalListenerForInnerCom(cluster.Spec.ListenersConfig.InternalListeners)].ContainerPort) + return fmt.Sprintf("%s:%d", GenerateKafkaAddressWithoutPort(cluster), getContainerPortForInnerCom( + cluster.Spec.ListenersConfig.InternalListeners, cluster.Spec.ListenersConfig.ExternalListeners)) } diff --git a/pkg/util/client/common_test.go b/pkg/util/client/common_test.go index cb90d1517..29f2532bc 100644 --- a/pkg/util/client/common_test.go +++ b/pkg/util/client/common_test.go @@ -33,7 +33,10 @@ func TestGenerateKafkaAddress(t *testing.T) { ListenersConfig: v1beta1.ListenersConfig{ InternalListeners: []v1beta1.InternalListenerConfig{ { - CommonListenerSpec: v1beta1.CommonListenerSpec{ContainerPort: 80}, + CommonListenerSpec: v1beta1.CommonListenerSpec{ + ContainerPort: 80, + UsedForInnerBrokerCommunication: true, + }, }, }, }, diff --git a/pkg/util/kafka/common.go b/pkg/util/kafka/common.go index 52ff1a97a..5656d1c57 100644 --- a/pkg/util/kafka/common.go +++ b/pkg/util/kafka/common.go @@ -189,30 +189,45 @@ func GetBootstrapServersService(cluster *v1beta1.KafkaCluster) (string, error) { return getBootstrapServers(cluster, true) } -func getBootstrapServers(cluster *v1beta1.KafkaCluster, useService bool) (string, error) { - var listener v1beta1.InternalListenerConfig - var bootstrapServersList []string +// GetBrokerContainerPort return broker container port +func GetBrokerContainerPort(cluster *v1beta1.KafkaCluster) (int32, error) { + containerPort := int32(0) for _, lc := range cluster.Spec.ListenersConfig.InternalListeners { if lc.UsedForInnerBrokerCommunication && !lc.UsedForControllerCommunication { - listener = lc + containerPort = lc.ContainerPort + break + } + } + + for _, lc := range cluster.Spec.ListenersConfig.ExternalListeners { + if lc.UsedForInnerBrokerCommunication { + containerPort = lc.ContainerPort break } } - if listener.Name == "" { - return "", errors.New("no suitable listener found for using as Kafka bootstrap server configuration") + if containerPort <= 0 { + return -1, errors.New("no suitable listener found for using as Kafka bootstrap server configuration") } + return containerPort, nil +} +func getBootstrapServers(cluster *v1beta1.KafkaCluster, useService bool) (string, error) { + containerPort, err := GetBrokerContainerPort(cluster) + if err != nil { + return "", err + } + var bootstrapServersList []string if useService { bootstrapServersList = append(bootstrapServersList, - fmt.Sprintf("%s:%d", GetClusterServiceFqdn(cluster), listener.ContainerPort)) + fmt.Sprintf("%s:%d", GetClusterServiceFqdn(cluster), containerPort)) } else { for _, broker := range cluster.Spec.Brokers { broker := broker fqdn := GetBrokerServiceFqdn(cluster, &broker) bootstrapServersList = append(bootstrapServersList, - fmt.Sprintf("%s:%d", fqdn, listener.ContainerPort)) + fmt.Sprintf("%s:%d", fqdn, containerPort)) } } return strings.Join(bootstrapServersList, ","), nil diff --git a/pkg/util/kafka/common_test.go b/pkg/util/kafka/common_test.go index 0c0ff54b8..52dff8f55 100644 --- a/pkg/util/kafka/common_test.go +++ b/pkg/util/kafka/common_test.go @@ -134,20 +134,20 @@ var MinimalKafkaCluster = &v1beta1.KafkaCluster{ InternalListeners: []v1beta1.InternalListenerConfig{ { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "internal", - ContainerPort: 29092, + Type: "plaintext", + Name: "internal", + ContainerPort: 29092, + UsedForInnerBrokerCommunication: true, }, - UsedForInnerBrokerCommunication: true, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ - Type: "plaintext", - Name: "controller", - ContainerPort: 29093, + Type: "plaintext", + Name: "controller", + ContainerPort: 29093, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, - UsedForControllerCommunication: true, + UsedForControllerCommunication: true, }, }, }, diff --git a/pkg/util/util.go b/pkg/util/util.go index 97a60b1c0..02b5cb1a6 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -31,11 +31,11 @@ import ( "strings" "time" + "dario.cat/mergo" "emperror.dev/errors" - "github.com/Shopify/sarama" + "github.com/IBM/sarama" clusterregv1alpha1 "github.com/cisco-open/cluster-registry-controller/api/v1alpha1" "github.com/go-logr/logr" - "github.com/imdario/mergo" "go.uber.org/zap" "go.uber.org/zap/zapcore" corev1 "k8s.io/api/core/v1" @@ -344,8 +344,6 @@ func GetBrokerMetricsReporterImage(brokerConfig *v1beta1.BrokerConfig, kafkaClus // getRandomString returns a random string containing uppercase, lowercase and number characters with the length given func GetRandomString(length int) (string, error) { - rand.Seed(time.Now().UnixNano()) - chars := []rune(symbolSet) var b strings.Builder @@ -539,7 +537,8 @@ func RetryOnError(backoff wait.Backoff, fn func() error, isRetryableError func(e return false, err } }) - if err == wait.ErrWaitTimeout { + + if wait.Interrupted(err) { err = lastErr } return err diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 8add02c4a..502ae9b5b 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -102,8 +102,10 @@ func TestConvertStringToInt32(t *testing.T) { func TestIsSSLEnabledForInternalCommunication(t *testing.T) { lconfig := []v1beta1.InternalListenerConfig{ { - UsedForInnerBrokerCommunication: true, - CommonListenerSpec: v1beta1.CommonListenerSpec{Type: "ssl"}, + CommonListenerSpec: v1beta1.CommonListenerSpec{ + Type: "ssl", + UsedForInnerBrokerCommunication: true, + }, }, } if !IsSSLEnabledForInternalCommunication(lconfig) { @@ -111,8 +113,10 @@ func TestIsSSLEnabledForInternalCommunication(t *testing.T) { } lconfig = []v1beta1.InternalListenerConfig{ { - UsedForInnerBrokerCommunication: true, - CommonListenerSpec: v1beta1.CommonListenerSpec{Type: "plaintext"}, + CommonListenerSpec: v1beta1.CommonListenerSpec{ + Type: "plaintext", + UsedForInnerBrokerCommunication: true, + }, }, } if IsSSLEnabledForInternalCommunication(lconfig) { diff --git a/pkg/webhooks/errors_test.go b/pkg/webhooks/errors_test.go index 8004144d6..3f6e15cf2 100644 --- a/pkg/webhooks/errors_test.go +++ b/pkg/webhooks/errors_test.go @@ -134,7 +134,7 @@ func TestIsAdmissionInvalidRemovingStorage(t *testing.T) { }{ { testName: "field.Invalid_removingStorage", - fieldErrs: append(field.ErrorList{}, field.Invalid(field.NewPath("spec").Child("brokers").Index(0).Child("brokerConfigGroup"), "test-broker-config-group", unsupportedRemovingStorageMsg+", provided brokerConfigGroup not found")), + fieldErrs: append(field.ErrorList{}, field.Invalid(field.NewPath("spec").Child("brokers").Index(0).Child("brokerConfigGroup"), "test-broker-config-group", unsupportedRemovingStorageMsg+", provided brokerConfigGroup not found.")), want: true, }, { diff --git a/pkg/webhooks/kafkacluster_validator.go b/pkg/webhooks/kafkacluster_validator.go index f3395b731..952abd140 100644 --- a/pkg/webhooks/kafkacluster_validator.go +++ b/pkg/webhooks/kafkacluster_validator.go @@ -18,9 +18,10 @@ import ( "context" "fmt" - "emperror.dev/errors" - "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" + + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" @@ -35,37 +36,27 @@ type KafkaClusterValidator struct { Log logr.Logger } -func (s KafkaClusterValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error { +func (s KafkaClusterValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { var allErrs field.ErrorList - kafkaClusterOld := oldObj.(*banzaicloudv1beta1.KafkaCluster) kafkaClusterNew := newObj.(*banzaicloudv1beta1.KafkaCluster) log := s.Log.WithValues("name", kafkaClusterNew.GetName(), "namespace", kafkaClusterNew.GetNamespace()) - fieldErr, err := checkBrokerStorageRemoval(&kafkaClusterOld.Spec, &kafkaClusterNew.Spec) - if err != nil { - log.Error(err, errorDuringValidationMsg) - return apierrors.NewInternalError(errors.WithMessage(err, errorDuringValidationMsg)) - } - if fieldErr != nil { - allErrs = append(allErrs, fieldErr) - } - listenerErrs := checkInternalAndExternalListeners(&kafkaClusterNew.Spec) if listenerErrs != nil { allErrs = append(allErrs, listenerErrs...) } if len(allErrs) == 0 { - return nil + return nil, nil } log.Info("rejected", "invalid field(s)", allErrs.ToAggregate().Error()) - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( kafkaClusterNew.GroupVersionKind().GroupKind(), kafkaClusterNew.Name, allErrs) } -func (s KafkaClusterValidator) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (s KafkaClusterValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { var allErrs field.ErrorList kafkaCluster := obj.(*banzaicloudv1beta1.KafkaCluster) log := s.Log.WithValues("name", kafkaCluster.GetName(), "namespace", kafkaCluster.GetNamespace()) @@ -76,88 +67,18 @@ func (s KafkaClusterValidator) ValidateCreate(ctx context.Context, obj runtime.O } if len(allErrs) == 0 { - return nil + return nil, nil } log.Info("rejected", "invalid field(s)", allErrs.ToAggregate().Error()) - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( kafkaCluster.GroupVersionKind().GroupKind(), kafkaCluster.Name, allErrs) } -func (s KafkaClusterValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error { - return nil -} - -// checkBrokerStorageRemoval checks if there is any broker storage which has been removed. If yes, admission will be rejected -func checkBrokerStorageRemoval(kafkaClusterSpecOld, kafkaClusterSpecNew *banzaicloudv1beta1.KafkaClusterSpec) (*field.Error, error) { - for j := range kafkaClusterSpecOld.Brokers { - brokerOld := &kafkaClusterSpecOld.Brokers[j] - for k := range kafkaClusterSpecNew.Brokers { - brokerNew := &kafkaClusterSpecNew.Brokers[k] - if brokerOld.Id == brokerNew.Id { - brokerConfigsOld, err := brokerOld.GetBrokerConfig(*kafkaClusterSpecOld) - if err != nil { - return nil, err - } - // checking brokerConfigGroup existence - if brokerNew.BrokerConfigGroup != "" { - if _, exists := kafkaClusterSpecNew.BrokerConfigGroups[brokerNew.BrokerConfigGroup]; !exists { - return field.Invalid(field.NewPath("spec").Child("brokers").Index(int(brokerNew.Id)).Child("brokerConfigGroup"), brokerNew.BrokerConfigGroup, unsupportedRemovingStorageMsg+", provided brokerConfigGroup not found"), nil - } - } - brokerConfigsNew, err := brokerNew.GetBrokerConfig(*kafkaClusterSpecNew) - if err != nil { - return nil, err - } - for e := range brokerConfigsOld.StorageConfigs { - storageConfigOld := &brokerConfigsOld.StorageConfigs[e] - isStorageFound := false - - for f := range brokerConfigsNew.StorageConfigs { - storageConfigNew := &brokerConfigsNew.StorageConfigs[f] - if storageConfigOld.MountPath == storageConfigNew.MountPath { - isStorageFound = true - break - } - } - if !isStorageFound { - fromConfigGroup := getMissingMounthPathLocation(storageConfigOld.MountPath, kafkaClusterSpecOld, int32(k)) - if fromConfigGroup != nil && *fromConfigGroup { - return field.Invalid(field.NewPath("spec").Child("brokers").Index(k).Child("brokerConfigGroup"), brokerNew.BrokerConfigGroup, fmt.Sprintf("%s, missing storageConfig mounthPath: %s", unsupportedRemovingStorageMsg, storageConfigOld.MountPath)), nil - } - return field.NotFound(field.NewPath("spec").Child("brokers").Index(k).Child("storageConfig").Index(e), storageConfigOld.MountPath+", "+unsupportedRemovingStorageMsg), nil - } - } - } - } - } +func (s KafkaClusterValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { return nil, nil } -func getMissingMounthPathLocation(mounthPath string, kafkaClusterSpec *banzaicloudv1beta1.KafkaClusterSpec, brokerId int32) (fromConfigGroup *bool) { - if brokerId < 0 || int(brokerId) >= len(kafkaClusterSpec.Brokers) { - return nil - } - - brokerConfigGroup := kafkaClusterSpec.Brokers[brokerId].BrokerConfigGroup - brokerConfigs, ok := kafkaClusterSpec.BrokerConfigGroups[brokerConfigGroup] - if !ok { - fromConfigGroup = util.BoolPointer(true) - } - idx := slices.IndexFunc(brokerConfigs.StorageConfigs, func(c banzaicloudv1beta1.StorageConfig) bool { return c.MountPath == mounthPath }) - if idx != -1 { - fromConfigGroup = util.BoolPointer(true) - } - - perBrokerConfigs := kafkaClusterSpec.Brokers[brokerId].BrokerConfig - if perBrokerConfigs != nil { - idx := slices.IndexFunc(perBrokerConfigs.StorageConfigs, func(c banzaicloudv1beta1.StorageConfig) bool { return c.MountPath == mounthPath }) - if idx != -1 { - fromConfigGroup = util.BoolPointer(false) - } - } - return fromConfigGroup -} // checkListeners validates the spec.listenersConfig object func checkInternalAndExternalListeners(kafkaClusterSpec *banzaicloudv1beta1.KafkaClusterSpec) field.ErrorList { @@ -245,7 +166,7 @@ func checkExternalListenerStartingPort(kafkaClusterSpec *banzaicloudv1beta1.Kafk } if len(collidingPortsBrokerIDs) > 0 { - errmsg := invalidExternalListenerStartingPortErrMsg + ": " + fmt.Sprintf("ExternalListener '%s' would generate external access port numbers ("+ + errmsg := invalidExternalListenerStartingPortErrMsg + ": " + fmt.Sprintf("ExternalListener '%s' would generate external access port numbers ("+ //nolint:goconst "externalStartingPort + Broker ID) that collide with either the envoy admin port ('%d'), the envoy health-check port ('%d'), or the ingressControllerTargetPort ('%d') for brokers %v", extListener.Name, kafkaClusterSpec.EnvoyConfig.GetEnvoyAdminPort(), kafkaClusterSpec.EnvoyConfig.GetEnvoyHealthCheckPort(), extListener.GetIngressControllerTargetPort(), collidingPortsBrokerIDs) fldErr := field.Invalid(field.NewPath("spec").Child("listenersConfig").Child("externalListeners").Index(i).Child("externalStartingPort"), extListener.ExternalStartingPort, errmsg) @@ -267,7 +188,7 @@ func checkTargetPortsCollisionForEnvoy(kafkaClusterSpec *banzaicloudv1beta1.Kafk hcp := kafkaClusterSpec.EnvoyConfig.GetEnvoyHealthCheckPort() if ap == hcp { - errmsg := invalidContainerPortForIngressControllerErrMsg + ": The envoy configuration uses an admin port number that collides with the health-check port number" + errmsg := invalidContainerPortForIngressControllerErrMsg + ": The envoy configuration uses an admin port number that collides with the health-check port number" //nolint:goconst fldErr := field.Invalid(field.NewPath("spec").Child("envoyConfig").Child("adminPort"), kafkaClusterSpec.EnvoyConfig.GetEnvoyAdminPort(), errmsg) allErrs = append(allErrs, fldErr) } diff --git a/pkg/webhooks/kafkacluster_validator_test.go b/pkg/webhooks/kafkacluster_validator_test.go index cbcfe4be0..fcb18a779 100644 --- a/pkg/webhooks/kafkacluster_validator_test.go +++ b/pkg/webhooks/kafkacluster_validator_test.go @@ -27,473 +27,6 @@ import ( "github.com/banzaicloud/koperator/api/v1beta1" ) -// nolint: funlen -func TestCheckBrokerStorageRemoval(t *testing.T) { - testCases := []struct { - testName string - kafkaClusterSpecNew v1beta1.KafkaClusterSpec - kafkaClusterSpecOld v1beta1.KafkaClusterSpec - isValid bool - }{ - { - testName: "there is no storage remove", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: true, - }, - { - testName: "there is no storage remove but there is broker remove", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - { - Id: 2, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: true, - }, - { - testName: "when there is storage remove but there is broker remove also", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - { - Id: 2, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs6"}, - }, - }, - }, - }, - }, - isValid: true, - }, - { - testName: "when there is storage remove from another brokerConfigBroup", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - "default2": { - StorageConfigs: []v1beta1.StorageConfig{ - // v1beta1.StorageConfig{MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default2", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: false, - }, - { - testName: "when there is storage remove", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - //v1beta1.StorageConfig{MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: false, - }, - { - testName: "when added a new one", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - //v1beta1.StorageConfig{MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: true, - }, - { - testName: "when only sequence has changed", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs3"}, - {MountPath: "logs2"}, - {MountPath: "logs1"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - }, - }, - }, - isValid: true, - }, - { - testName: "when there is perBroker storageconfigs and there is no storage remove", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs6"}, - }, - }, - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs6"}, - }, - }, - }, - }, - }, - isValid: true, - }, - { - testName: "when there is perBroker config and added new and removed old", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs6"}, - }, - }, - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs8"}, - }, - }, - }, - }, - }, - isValid: false, - }, - { - testName: "when there is no such brokerConfigGroup", - kafkaClusterSpecNew: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "notExists", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs6"}, - }, - }, - }, - }, - }, - kafkaClusterSpecOld: v1beta1.KafkaClusterSpec{ - BrokerConfigGroups: map[string]v1beta1.BrokerConfig{ - "default": { - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs1"}, - {MountPath: "logs2"}, - {MountPath: "logs3"}, - }, - }, - }, - Brokers: []v1beta1.Broker{ - { - Id: 1, - BrokerConfigGroup: "default", - BrokerConfig: &v1beta1.BrokerConfig{ - StorageConfigs: []v1beta1.StorageConfig{ - {MountPath: "logs4"}, - {MountPath: "logs5"}, - {MountPath: "logs8"}, - }, - }, - }, - }, - }, - isValid: false, - }, - } - - for _, testCase := range testCases { - res, err := checkBrokerStorageRemoval(&testCase.kafkaClusterSpecOld, &testCase.kafkaClusterSpecNew) - if err != nil { - t.Errorf("testName: %s, err should be nil, got %s", testCase.testName, err) - } - if res != nil && testCase.isValid { - t.Errorf("Message: %s, testName: %s", res.Error(), testCase.testName) - } else if res == nil && !testCase.isValid { - t.Errorf("there should be storage removal, testName: %s", testCase.testName) - } - } -} - func TestCheckUniqueListenerContainerPort(t *testing.T) { testCases := []struct { testName string diff --git a/pkg/webhooks/kafkatopic_validator.go b/pkg/webhooks/kafkatopic_validator.go index c0c509326..515e6a54c 100644 --- a/pkg/webhooks/kafkatopic_validator.go +++ b/pkg/webhooks/kafkatopic_validator.go @@ -19,6 +19,8 @@ import ( "fmt" "strings" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + "emperror.dev/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -49,32 +51,32 @@ type KafkaTopicValidator struct { Log logr.Logger } -func (s KafkaTopicValidator) ValidateCreate(ctx context.Context, obj runtime.Object) error { +func (s KafkaTopicValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { return s.validate(ctx, obj) } -func (s KafkaTopicValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error { +func (s KafkaTopicValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { return s.validate(ctx, newObj) } -func (s KafkaTopicValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error { - return nil +func (s KafkaTopicValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + return nil, nil } -func (s *KafkaTopicValidator) validate(ctx context.Context, obj runtime.Object) error { +func (s *KafkaTopicValidator) validate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { kafkaTopic := obj.(*banzaicloudv1alpha1.KafkaTopic) log := s.Log.WithValues("name", kafkaTopic.GetName(), "namespace", kafkaTopic.GetNamespace()) fieldErrs, err := s.validateKafkaTopic(ctx, log, kafkaTopic) if err != nil { log.Error(err, errorDuringValidationMsg) - return apierrors.NewInternalError(errors.WithMessage(err, errorDuringValidationMsg)) + return nil, apierrors.NewInternalError(errors.WithMessage(err, errorDuringValidationMsg)) } if len(fieldErrs) == 0 { - return nil + return nil, nil } log.Info("rejected", "invalid field(s)", fieldErrs.ToAggregate().Error()) - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( kafkaTopic.GetObjectKind().GroupVersionKind().GroupKind(), kafkaTopic.Name, fieldErrs) } diff --git a/properties/go.mod b/properties/go.mod index af5d51e26..983c85724 100644 --- a/properties/go.mod +++ b/properties/go.mod @@ -1,18 +1,20 @@ module github.com/banzaicloud/koperator/properties -go 1.19 +go 1.21 require ( emperror.dev/errors v0.8.1 - github.com/onsi/gomega v1.27.8 + github.com/onsi/gomega v1.30.0 ) require ( - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/pkg/errors v0.9.1 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/text v0.9.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +// remove once https://github.com/cert-manager/cert-manager/issues/5953 is fixed +replace github.com/Venafi/vcert/v4 => github.com/jetstack/vcert/v4 v4.9.6-0.20230127103832-3aa3dfd6613d diff --git a/properties/go.sum b/properties/go.sum index ee3525d87..bd21e6d01 100644 --- a/properties/go.sum +++ b/properties/go.sum @@ -4,30 +4,37 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/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-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -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/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/tests/e2e/const.go b/tests/e2e/const.go index f6f575f6b..ab9888543 100644 --- a/tests/e2e/const.go +++ b/tests/e2e/const.go @@ -94,7 +94,6 @@ func basicK8sResourceKinds() []string { "jobs.batch", "cronjobs.batch", "poddisruptionbudgets.policy", - "podsecuritypolicies.policy", "persistentvolumeclaims", "persistentvolumes", } diff --git a/tests/e2e/global.go b/tests/e2e/global.go index 6baa274f4..4c187073f 100644 --- a/tests/e2e/global.go +++ b/tests/e2e/global.go @@ -87,7 +87,7 @@ var ( prometheusOperatorHelmDescriptor = helmDescriptor{ Repository: "https://prometheus-community.github.io/helm-charts", ChartName: "kube-prometheus-stack", - ChartVersion: "42.0.1", + ChartVersion: "54.1.0", ReleaseName: "prometheus-operator", Namespace: "prometheus", SetValues: map[string]string{ @@ -113,7 +113,7 @@ var ( zookeeperOperatorHelmDescriptor = helmDescriptor{ Repository: "https://charts.pravega.io", ChartName: "zookeeper-operator", - ChartVersion: "0.2.14", + ChartVersion: "0.2.15", ReleaseName: "zookeeper-operator", Namespace: "zookeeper", SetValues: map[string]string{ diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index 29b3191f0..9bf95f22e 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -1,6 +1,6 @@ module github.com/banzaicloud/koperator/tests/e2e -go 1.19 +go 1.21 require ( emperror.dev/errors v0.8.1 @@ -8,74 +8,75 @@ require ( github.com/banzaicloud/koperator v0.25.1 github.com/banzaicloud/koperator/api v0.28.8 github.com/cisco-open/k8s-objectmatcher v1.9.0 - github.com/gruntwork-io/terratest v0.41.26 - github.com/onsi/ginkgo/v2 v2.9.5 - github.com/onsi/gomega v1.27.6 - github.com/twmb/franz-go v1.13.5 - k8s.io/apiextensions-apiserver v0.26.4 - k8s.io/apimachinery v0.26.4 - sigs.k8s.io/yaml v1.3.0 + github.com/gruntwork-io/terratest v0.46.7 + github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/gomega v1.30.0 + github.com/twmb/franz-go v1.15.2 + k8s.io/apiextensions-apiserver v0.28.4 + k8s.io/apimachinery v0.28.4 + sigs.k8s.io/yaml v1.4.0 ) require ( + dario.cat/mergo v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Shopify/sarama v1.36.0 // indirect - github.com/aws/aws-sdk-go v1.44.122 // indirect + github.com/aws/aws-sdk-go v1.48.0 // indirect github.com/banzaicloud/istio-client-go v0.0.17 // indirect github.com/banzaicloud/koperator/properties v0.4.1 // indirect - github.com/banzaicloud/operator-tools v0.28.0 // indirect - github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect - github.com/briandowns/spinner v1.12.0 // indirect - github.com/cert-manager/cert-manager v1.11.2 // indirect - github.com/cisco-open/cluster-registry-controller/api v0.2.5 // indirect + github.com/banzaicloud/operator-tools v0.28.10 // indirect + github.com/boombuler/barcode v1.0.1 // indirect + github.com/briandowns/spinner v1.23.0 // indirect + github.com/cert-manager/cert-manager v1.13.2 // indirect + github.com/cisco-open/cluster-registry-controller/api v0.2.12 // indirect github.com/cppforlife/go-patch v0.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/eapache/go-resiliency v1.3.0 // indirect - github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/eapache/go-resiliency v1.4.0 // indirect + github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect github.com/eapache/queue v1.1.0 // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch v5.7.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect - github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect - github.com/go-logr/logr v1.2.4 // indirect - github.com/go-logr/zapr v1.2.3 // 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.19.14 // indirect - github.com/go-sql-driver/mysql v1.4.1 // indirect + github.com/go-errors/errors v1.5.1 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/gruntwork-io/go-commons v0.8.0 // indirect + github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/gruntwork-io/go-commons v0.17.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/huandu/xstrings v1.3.3 // indirect - github.com/iancoleman/orderedmap v0.2.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect - github.com/jcmturner/gokrb5/v8 v8.4.3 // indirect + github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/klauspost/compress v1.17.3 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -84,45 +85,49 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1 // indirect - github.com/pierrec/lz4/v4 v4.1.17 // indirect + github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 // indirect + github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/pquerna/otp v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pquerna/otp v1.4.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.1 // indirect - github.com/tidwall/gjson v1.9.3 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/tidwall/gjson v1.17.0 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect - github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect - github.com/urfave/cli v1.22.2 // indirect - github.com/wayneashleyberry/terminal-dimensions v1.0.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.9.1 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/twmb/franz-go/pkg/kmsg v1.7.0 // indirect + github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/oauth2 v0.14.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.4.0 // indirect + golang.org/x/tools v0.15.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.26.4 // indirect - k8s.io/client-go v0.26.4 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 // indirect - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect - sigs.k8s.io/controller-runtime v0.14.6 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + k8s.io/api v0.28.4 // indirect + k8s.io/client-go v0.28.4 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/controller-runtime v0.16.3 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) + +replace github.com/banzaicloud/koperator/api => ../../api + +replace github.com/banzaicloud/koperator/properties => ../../properties diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index c69c724d9..7335db109 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -30,6 +30,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo 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= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= @@ -41,7 +43,6 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.36.0 h1:0OJs3eCcnezkWniVjwBbCJVaa0B1k7ImCRS3WN6NsSk= github.com/Shopify/sarama v1.36.0/go.mod h1:9glG3eX83tgVYJ5aVtrjVUnEsOPqQIBGx1BWfN+X51I= github.com/Shopify/toxiproxy/v2 v2.4.0 h1:O1e4Jfvr/hefNTNu+8VtdEG5lSeamJRo4aKhMOKNM64= @@ -51,96 +52,83 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= -github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go v1.48.0 h1:1SeJ8agckRDQvnSCt1dGZYAwUaoD2Ixj6IaXB4LCv8Q= +github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/banzaicloud/istio-client-go v0.0.17 h1:wiplbM7FDiIHopujInAnin3zuovtVcphtKy9En39q5I= github.com/banzaicloud/istio-client-go v0.0.17/go.mod h1:rpnEYYGHzisx8nARl2d30Oq38EeCX0/PPaxMaREfE9I= github.com/banzaicloud/koperator v0.25.1 h1:baWLnsMOitml8bJ/6zAH1XGYdqM0mu9YzQY6zioKxlk= github.com/banzaicloud/koperator v0.25.1/go.mod h1:QLU5npzAcVE1cCxtPrnpWsw3Pm59TVikXFu65ZDNImw= -github.com/banzaicloud/koperator/api v0.28.8 h1:7J6B+s9D5WhTNKC5oQwk4USN4h2gUP4GLfNmfq2yb1c= -github.com/banzaicloud/koperator/api v0.28.8/go.mod h1:AGGQ+aTBklaaG8ErotNPlP/nS47MYLc/jFVW7AsDiEE= -github.com/banzaicloud/koperator/properties v0.4.1 h1:SB2QgXlcK1Dc7Z1rg65PJifErDa8OQnoWCCJgmC7SGc= -github.com/banzaicloud/koperator/properties v0.4.1/go.mod h1:TcL+llxuhW3UeQtVEDYEXGouFLF2P+LuZZVudSb6jyA= -github.com/banzaicloud/operator-tools v0.28.0 h1:GSfc0qZr6zo7WrNxdgWZE1LcTChPU8QFYOTDirYVtIM= -github.com/banzaicloud/operator-tools v0.28.0/go.mod h1:t0dyFGJUR9Q5CwsUcq1nDJC0wSZqeh6nzUZkUp3vCXg= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/banzaicloud/operator-tools v0.28.10 h1:mm+LvL31GV9BL//zs/CTKVcFdHHyZ+KIbuNoXrOo3gA= +github.com/banzaicloud/operator-tools v0.28.10/go.mod h1:PhwQ6bn1blX+SuH5ALj3Fwvvmsi1KdAwke8NufILY8I= 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/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= -github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= +github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cert-manager/cert-manager v1.11.2 h1:rJMZv9VtN0YhHZn1esj+V0+KhrYUF8d0BMJWUeIrKX4= -github.com/cert-manager/cert-manager v1.11.2/go.mod h1:hZshV9rYSanOsbRcQHyRmrvhtq/pj0L9+Hg10Do9NgI= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cert-manager/cert-manager v1.13.2 h1:LG8+OLvxtc49CSyfjW7zHSyvlt7JVaHgRGyhfdvPpkk= +github.com/cert-manager/cert-manager v1.13.2/go.mod h1:AdfSU8muS+bj3C46YaD1VrlpXh672z5MeW/k1k5Sl1w= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/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/cisco-open/cluster-registry-controller/api v0.2.5 h1:ylJwxnOXlgjoAPYmwNGoFl8Ja4rHBQzAlnoDIkP30lA= -github.com/cisco-open/cluster-registry-controller/api v0.2.5/go.mod h1:+SGsAzdHbD+v+CovGDNqbfEg48p/EiopbLvYZj56Vgg= +github.com/cisco-open/cluster-registry-controller/api v0.2.12 h1:dxKVG3T75RAU8f0kmeLRh82Ao4koTFIPZEodUTBhg14= +github.com/cisco-open/cluster-registry-controller/api v0.2.12/go.mod h1:zRJ4y4xZlEq1AkOm8pd6qpH7WQ9yinLaE3SA30TWh74= github.com/cisco-open/k8s-objectmatcher v1.9.0 h1:/sfuO0BD09fpynZjXsqeZrh28Juc4VEwc2P6Ov/Q6fM= github.com/cisco-open/k8s-objectmatcher v1.9.0/go.mod h1:CH4E6qAK+q+JwKFJn0DaTNqxrbmWCaDQzGthKLK4nZ0= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cppforlife/go-patch v0.2.0 h1:Y14MnCQjDlbw7WXT4k+u6DPAA9XnygN4BfrSpI/19RU= github.com/cppforlife/go-patch v0.2.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= 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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/eapache/go-resiliency v1.3.0 h1:RRL0nge+cWGlxXbUzJ7yMcq6w2XBEr19dCN6HECGaT0= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/eapache/go-resiliency v1.3.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= +github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0= +github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik= -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/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -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/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/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 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= +github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU= -github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= 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= @@ -151,27 +139,26 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -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/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -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.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= +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/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= 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/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/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -209,8 +196,8 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/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/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= 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= @@ -220,8 +207,9 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.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= @@ -234,23 +222,21 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf 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-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/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/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.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/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro= -github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= -github.com/gruntwork-io/terratest v0.41.26 h1:ttDXBBDBAYV4KgP1itGQ5O61F6KwgMMUFHy64bzvuYU= -github.com/gruntwork-io/terratest v0.41.26/go.mod h1:O6gajNBjO1wvc7Wl9WtbO+ORcdnhAV2GQiBE71ycwIk= +github.com/gruntwork-io/go-commons v0.17.1 h1:2KS9wAqrgeOTWj33DSHzDNJ1FCprptWdLFqej+wB8x0= +github.com/gruntwork-io/go-commons v0.17.1/go.mod h1:S98JcR7irPD1bcruSvnqupg+WSJEJ6xaM89fpUZVISk= +github.com/gruntwork-io/terratest v0.46.7 h1:oqGPBBO87SEsvBYaA0R5xOq+Lm2Xc5dmFVfxEolfZeU= +github.com/gruntwork-io/terratest v0.46.7/go.mod h1:6gI5MlLeyF+SLwqocA5GBzcTix+XiuxCy1BPwKuT+WM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -262,12 +248,11 @@ github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b 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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= -github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= 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.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= @@ -278,13 +263,13 @@ github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVET github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.3 h1:iTonLeSJOn7MVUtyMT+arAn5AKAPrkilzhGw8wE/Tq8= github.com/jcmturner/gokrb5/v8 v8.4.3/go.mod h1:dqRwJGXznQrzw6cWmyo6kH+E7jksEQG/CyVWsJEsJO0= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -303,40 +288,32 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= 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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 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/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/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.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -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-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= -github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= -github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= +github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 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/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -356,7 +333,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq 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/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= @@ -364,53 +340,58 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= +github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= 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.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1 h1:FyBdsRqqHH4LctMLL+BL2oGO+ONcIPwn96ctofCVtNE= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.4.1/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 h1:2nosf3P75OZv2/ZO/9Px5ZgZ5gbKrzA3joN1QMfOGMQ= +github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= -github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.0/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= -github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= +github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 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.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +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.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/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +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.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/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.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -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/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -419,13 +400,11 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx 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.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= 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/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.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -435,61 +414,61 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV 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/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +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/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= +github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/twmb/franz-go v1.13.5 h1:7Hk47eZ7XRb4yWXQZk1GZU4BthkrKuZUfKOuP9Sgp24= -github.com/twmb/franz-go v1.13.5/go.mod h1:jm/FtYxmhxDTN0gNSb26XaJY0irdSVcsckLiR5tQNMk= -github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s= -github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY= -github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/twmb/franz-go v1.15.2 h1:mt3i7bTAp4GH/kMJiGAikJQUlG+UsCwxCmEy1CcAKYo= +github.com/twmb/franz-go v1.15.2/go.mod h1:aos+d/UBuigWkOs+6WoqEPto47EvC2jipLAO5qrAu48= +github.com/twmb/franz-go/pkg/kmsg v1.7.0 h1:a457IbvezYfA5UkiBvyV3zj0Is3y1i8EJgqjJYoij2E= +github.com/twmb/franz-go/pkg/kmsg v1.7.0/go.mod h1:se9Mjdt0Nwzc9lnjJ0HyDtLyBnaBDAd7pCje47OhSyw= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/wayneashleyberry/terminal-dimensions v1.0.0 h1:LawtS1nqKjAfqrmKOzkcrDLAjSzh38lEhC401JPjQVA= -github.com/wayneashleyberry/terminal-dimensions v1.0.0/go.mod h1:PW2XrtV6KmKOPhuf7wbtcmw1/IFnC39mryRET2XbxeE= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/wayneashleyberry/terminal-dimensions v1.1.0 h1:EB7cIzBdsOzAgmhTUtTTQXBByuPheP/Zv1zL2BRPY6g= +github.com/wayneashleyberry/terminal-dimensions v1.1.0/go.mod h1:2lc/0eWCObmhRczn2SdGSQtgBooLUzIotkkEGXqghyg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -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 v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 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.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +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.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +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.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= 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= @@ -500,8 +479,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 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/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -522,7 +501,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB 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.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -555,23 +536,24 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R 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-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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= golang.org/x/net v0.0.0-20220809184613-07c6da5e1ced/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= 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-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= 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= @@ -583,13 +565,13 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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= @@ -607,7 +589,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200122134326-e047566fdf82/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= @@ -626,38 +607,39 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210603081109-ebe580a85c40/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-20210630005230-0f9fa26af87c/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= 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.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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= +golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -674,7 +656,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/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-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= @@ -703,13 +684,15 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 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.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= 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= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +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/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= @@ -732,8 +715,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 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= @@ -757,14 +740,12 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/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-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -777,9 +758,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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= @@ -792,14 +770,12 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -818,12 +794,11 @@ 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= 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= @@ -831,31 +806,31 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94= -k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk= -k8s.io/apiextensions-apiserver v0.26.4 h1:9D2RTxYGxrG5uYg6D7QZRcykXvavBvcA59j5kTaedQI= -k8s.io/apiextensions-apiserver v0.26.4/go.mod h1:cd4uGFGIgzEqUghWpRsr9KE8j2KNTjY8Ji8pnMMazyw= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= +k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= +k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= -k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.26.4 h1:/7P/IbGBuT73A+G97trf44NTPSNqvuBREpOfdLbHvD4= -k8s.io/client-go v0.26.4/go.mod h1:6qOItWm3EwxJdl/8p5t7FWtWUOwyMdA8N9ekbW4idpI= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 h1:tBEbstoM+K0FiBV5KGAKQ0kuvf54v/hwpldiJt69w1s= -k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e h1:snPmy96t93RredGRjKfMFt+gvxuVAncqSAyBveJtr4Q= +k8s.io/kube-openapi v0.0.0-20231113174909-778a5567bc1e/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 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/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= -sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -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.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= +sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +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.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=