From d2b80216c7222ec5f306fd49a13751bb22097744 Mon Sep 17 00:00:00 2001 From: Adrian Lungu Date: Tue, 7 Feb 2023 15:53:43 +0200 Subject: [PATCH 01/23] [INTERNAL] Update helm for adobe builds (#52) --- .github/workflows/helm.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index 6db57bc35..bb7391e4b 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: From a5ea1119304770a121532adbc7bfd4f1c85987a2 Mon Sep 17 00:00:00 2001 From: aguzovatii Date: Thu, 6 Apr 2023 16:03:53 +0300 Subject: [PATCH 02/23] [INTERNAL] Use local replacement for sub-modules (#54) As part of https://github.com/banzaicloud/koperator/pull/929, the local replacement for sub-modules was removed in favor of using valid tags. Adobe Koperator fork has some internal changes in the api sub-module, so we need to use the local version of the sub-module instead of the upstream version, so we are forced to revert the changes from #929. --- go.mod | 2 ++ go.sum | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 106c421c3..9a7581506 100644 --- a/go.mod +++ b/go.mod @@ -137,6 +137,8 @@ require ( ) replace ( + 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 ) diff --git a/go.sum b/go.sum index ee7951bc7..af972fd8d 100644 --- a/go.sum +++ b/go.sum @@ -64,10 +64,6 @@ github.com/banzaicloud/istio-operator/api/v2 v2.15.1 h1:BZg8COvoOJtfx/dgN7KpoOnc github.com/banzaicloud/istio-operator/api/v2 v2.15.1/go.mod h1:5qCpwWlIfxiLvBfTvT2mD2wp5RlFCDEt8Xql4sYPNBc= 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= From c1173d01a94d7534d7197318123dd1ca877555e1 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Sat, 11 Apr 2020 03:06:19 +0300 Subject: [PATCH 03/23] [INTERNAL] [BUILD] Publish docker images to adobe/kafka-operator and adobe/kafka docker hub repos - build the koperator docker image - build Apache kafka docker image When `kafka-*` tags are created a github action is triggered to build and push a new adobe/kafka docker image version Allow broker libs injector to copy jars into KAFKA_HOME --- .github/CODEOWNERS | 2 - .github/workflows/build-push-docker.yml | 26 +++++++ .github/workflows/build-push-kafka-docker.yml | 44 ++++++++++++ .github/workflows/codeql-analysis.yml | 71 +++++++++++++++++++ .github/workflows/docker.yml | 56 --------------- .github/workflows/docker_perf_test_load.yml | 64 ----------------- .github/workflows/helm.yml | 8 +-- .github/workflows/release.yml | 57 --------------- docker/kafka/Dockerfile | 45 ++++++++++++ docker/kafka/README.md | 13 ++++ .../kafka/opt/kafka/config/log4j.properties | 50 +++++++++++++ 11 files changed, 250 insertions(+), 186 deletions(-) delete mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/build-push-docker.yml create mode 100644 .github/workflows/build-push-kafka-docker.yml create mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 .github/workflows/docker.yml delete mode 100644 .github/workflows/docker_perf_test_load.yml delete mode 100644 .github/workflows/release.yml create mode 100644 docker/kafka/Dockerfile create mode 100644 docker/kafka/README.md create mode 100644 docker/kafka/opt/kafka/config/log4j.properties 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/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/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/helm.yml b/.github/workflows/helm.yml index bb7391e4b..78658c60a 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -66,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/docker/kafka/Dockerfile b/docker/kafka/Dockerfile new file mode 100644 index 000000000..426e05a34 --- /dev/null +++ b/docker/kafka/Dockerfile @@ -0,0 +1,45 @@ +FROM alpine:latest AS kafka_dist + +ARG scala_version=2.13 +ARG kafka_version=2.6.2 +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 + + +FROM azul/zulu-openjdk:16.0.1 + +ARG scala_version=2.13 +ARG kafka_version=2.6.2 + +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..1612bce88 --- /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 16` 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 From e5152f78be8fe6d671b5d16585d71b25b005d5d7 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Wed, 28 Jul 2021 12:35:48 +0300 Subject: [PATCH 04/23] [INTERNAL] make manifests should be called manually, if needed (#25) We made some chnages for spinnaker annotations and `preserveUnknownFields` that would be overriden by `make manifests` --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ef78467e8..f9cef8ffc 100644 --- a/Makefile +++ b/Makefile @@ -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 From fe9adaf358f727375a9a093d62383ca830743997 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Mon, 17 May 2021 13:35:25 +0300 Subject: [PATCH 05/23] [INTERNAL] Allow Kafka to use External DNS for inter-broker protocol (#17) (#22) --- api/v1beta1/kafkacluster_types.go | 8 +++++++ pkg/k8sutil/status.go | 35 ++++++++++++++++++++++++------- pkg/resources/kafka/kafka.go | 2 +- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/api/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index 7ac56ad78..e2019cb40 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -678,6 +678,14 @@ type InternalListenerConfig struct { CommonListenerSpec `json:",inline"` UsedForInnerBrokerCommunication bool `json:"usedForInnerBrokerCommunication"` 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 diff --git a/pkg/k8sutil/status.go b/pkg/k8sutil/status.go index 035eb3617..fe6713b56 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" @@ -354,7 +355,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 +375,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 +407,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/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index a76f196e3..cd1ebb2f1 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -247,7 +247,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") From 8ca9d51ab3319e3510d0a8e357f97e8f627d32f6 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Mon, 17 May 2021 13:52:39 +0300 Subject: [PATCH 06/23] [INTERNAL] Allow external listeners to be used for inner communication (#26) --- api/v1beta1/kafkacluster_types.go | 8 ++- .../tests/clusterregistry/common_test.go | 18 +++--- controllers/tests/common_test.go | 18 +++--- .../currentalert/current_alerts_test.go | 8 +-- pkg/resources/kafka/configmap.go | 7 +++ pkg/resources/kafka/configmap_test.go | 4 +- pkg/resources/kafka/kafka_test.go | 56 +++++++++---------- pkg/util/client/common.go | 27 +++++++-- pkg/util/client/common_test.go | 5 +- pkg/util/kafka/common.go | 31 +++++++--- pkg/util/kafka/common_test.go | 18 +++--- pkg/util/util_test.go | 12 ++-- 12 files changed, 129 insertions(+), 83 deletions(-) diff --git a/api/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index e2019cb40..6ec98efbc 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -675,9 +675,8 @@ 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 @@ -706,6 +705,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/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/common_test.go b/controllers/tests/common_test.go index 15938c3e9..12931a799 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, }, }, }, 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/pkg/resources/kafka/configmap.go b/pkg/resources/kafka/configmap.go index 33b4fdffa..79137aa03 100644 --- a/pkg/resources/kafka/configmap.go +++ b/pkg/resources/kafka/configmap.go @@ -292,6 +292,13 @@ func generateListenerSpecificConfig(l *v1beta1.ListenersConfig, serverPasses map } 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)) diff --git a/pkg/resources/kafka/configmap_test.go b/pkg/resources/kafka/configmap_test.go index 671a352d0..3890e7fcc 100644 --- a/pkg/resources/kafka/configmap_test.go +++ b/pkg/resources/kafka/configmap_test.go @@ -640,9 +640,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/kafka_test.go b/pkg/resources/kafka/kafka_test.go index 0aba87a46..23d5e4be8 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -603,11 +603,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 +643,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 +726,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 +756,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -819,8 +819,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, { CommonListenerSpec: v1beta1.CommonListenerSpec{ @@ -830,8 +830,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, SSLSecrets: &v1beta1.SSLSecrets{}, @@ -851,11 +851,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 +865,8 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen ServerSSLCertSecret: &corev1.LocalObjectReference{ Name: "customcert", }, + UsedForInnerBrokerCommunication: false, }, - UsedForInnerBrokerCommunication: false, }, }, }, 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_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) { From 4335c202f9d33608d76a17e6c2862328038acd2e Mon Sep 17 00:00:00 2001 From: Adrian Lungu Date: Thu, 2 Sep 2021 15:24:40 +0300 Subject: [PATCH 07/23] [INTERNAL] Ensure external listerners are always the first the advertised.listeners configuration This is needed for old clients connecting to kafka through Zookeeper that does not have a way to infer the right listener. In this case, the first listener in the advertised.listener config is used to connect to brokers. This patch ensures the external listeners (those reachable from outside) are listed before internal ones --- ...ontroller_externallistenerbindings_test.go | 20 ++++---- .../kafkacluster_controller_kafka_test.go | 8 ++-- pkg/resources/kafka/configmap.go | 46 ++++++++++--------- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go b/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go index 8778db1b0..31f96146c 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,8 @@ 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 expectBrokerConfigmapForAz2ExternalListener(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster, randomGenTestNumber uint64) { @@ -129,8 +129,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 +144,6 @@ 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))) } 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/pkg/resources/kafka/configmap.go b/pkg/resources/kafka/configmap.go index 79137aa03..4c00eabf0 100644 --- a/pkg/resources/kafka/configmap.go +++ b/pkg/resources/kafka/configmap.go @@ -202,13 +202,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 +274,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,23 +310,6 @@ func generateListenerSpecificConfig(l *v1beta1.ListenersConfig, serverPasses map } } - 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) - } - } 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)) } From 685da4e951879a48f9a5ff02a658788f8a7ed810 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Thu, 2 Sep 2021 14:43:03 +0300 Subject: [PATCH 08/23] [INTERNAL] Generate CRDs resources --- charts/kafka-operator/crds/kafkaclusters.yaml | 22 ++++++++++++++++--- .../kafka.banzaicloud.io_kafkaclusters.yaml | 22 ++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/charts/kafka-operator/crds/kafkaclusters.yaml b/charts/kafka-operator/crds/kafkaclusters.yaml index 8ed2611c4..6790cb5b0 100644 --- a/charts/kafka-operator/crds/kafkaclusters.yaml +++ b/charts/kafka-operator/crds/kafkaclusters.yaml @@ -21322,7 +21322,6 @@ spec: minimum: 1024 type: integer name: - pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21372,6 +21371,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,8 +21393,20 @@ 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 serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21432,12 +21447,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: diff --git a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml index 8ed2611c4..6790cb5b0 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml @@ -21322,7 +21322,6 @@ spec: minimum: 1024 type: integer name: - pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21372,6 +21371,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,8 +21393,20 @@ 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 serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21432,12 +21447,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: From 84345fcfae242703cb01a384442c9ca06dcbe6eb Mon Sep 17 00:00:00 2001 From: Adrian Muraru Date: Tue, 21 Sep 2021 11:51:35 +0300 Subject: [PATCH 09/23] [INTERNAL] Build kafka 3.4.1 using Oracle OpenJDK --- docker/kafka/Dockerfile | 85 ++++++++++++++++++- docker/kafka/README.md | 2 +- .../kafka/opt/kafka/config/log4j.properties | 1 + 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/docker/kafka/Dockerfile b/docker/kafka/Dockerfile index 426e05a34..bee83178b 100644 --- a/docker/kafka/Dockerfile +++ b/docker/kafka/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:latest AS kafka_dist ARG scala_version=2.13 -ARG kafka_version=2.6.2 +ARG kafka_version=3.4.1 ARG kafka_distro_base_url=https://downloads.apache.org/kafka ENV kafka_distro=kafka_$scala_version-$kafka_version.tgz @@ -22,10 +22,89 @@ RUN tar -xzf $kafka_distro RUN rm -r kafka_$scala_version-$kafka_version/bin/windows -FROM azul/zulu-openjdk:16.0.1 +# 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=2.6.2 +ARG kafka_version=3.4.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-17 +ENV PATH $JAVA_HOME/bin:$PATH + +# Default to UTF-8 file.encoding +ENV LANG C.UTF-8 +RUN set -eux; \ + \ + arch="$(dpkg --print-architecture)"; \ + case "$arch" in \ + 'amd64') \ + downloadUrl='https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz'; \ + downloadSha256='https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz.sha256'; \ + ;; \ + 'arm64') \ + downloadUrl='https://download.oracle.com/java/17/latest/jdk-17_linux-aarch64_bin.tar.gz'; \ + downloadSha256='https://download.oracle.com/java/17/latest/jdk-17_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 \ diff --git a/docker/kafka/README.md b/docker/kafka/README.md index 1612bce88..67a9fbf53 100644 --- a/docker/kafka/README.md +++ b/docker/kafka/README.md @@ -9,5 +9,5 @@ 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 16` in order to support container based resource monitoring +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 index c56208444..73b58315f 100644 --- a/docker/kafka/opt/kafka/config/log4j.properties +++ b/docker/kafka/opt/kafka/config/log4j.properties @@ -18,6 +18,7 @@ log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.immediateFlush=true log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c)%n From 9b060e228da2a649c81de48a081d501e947251e4 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Fri, 8 Oct 2021 00:05:44 +0300 Subject: [PATCH 10/23] Enable envoy idleTimeout and TCP keep-alive for connections to kafka and clients 1/ Kafka broker defines connections.max.idle.ms=600s To ensure envoy as a client for kafka broker is terminating the connection first to avoid network disconnects this patch is setting the idleTimeout to value slightly less than that 2/ Enable tcp-keep alive for all TCP connections established by envoy to kafka and to client (or fronting Load Balancer) --- .../kafkacluster_controller_envoy_test.go | 210 ++++++++++++++++++ pkg/resources/envoy/configmap.go | 69 +++++- 2 files changed, 274 insertions(+), 5 deletions(-) diff --git a/controllers/tests/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 7a7d7ae78..6fed15d9f 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 @@ -291,6 +367,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 +562,11 @@ staticResources: portValue: 9094 name: broker-0 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -510,6 +604,11 @@ staticResources: portValue: 9020 name: all-brokers type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 listeners: - address: socketAddress: @@ -521,8 +620,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 +646,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 @@ -576,6 +703,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, "all-broker")) Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) } @@ -688,6 +828,11 @@ staticResources: portValue: 9094 name: broker-1 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -711,6 +856,11 @@ staticResources: portValue: 9094 name: broker-2 type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 - circuitBreakers: thresholds: - maxConnections: 1000000000 @@ -748,6 +898,11 @@ staticResources: portValue: 9020 name: all-brokers type: STRICT_DNS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 30 + keepaliveProbes: 3 + keepaliveTime: 30 listeners: - address: socketAddress: @@ -759,8 +914,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 +940,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 +966,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 @@ -826,6 +1023,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, "1"), fmt.Sprintf(svcTemplate, "2"), fmt.Sprintf(svcTemplate, "all-broker")) Expect(configMap.Data["envoy.yaml"]).To(Equal(expected)) } diff --git a/pkg/resources/envoy/configmap.go b/pkg/resources/envoy/configmap.go index a2e2a325b..31589f199 100644 --- a/pkg/resources/envoy/configmap.go +++ b/pkg/resources/envoy/configmap.go @@ -203,6 +203,7 @@ func generateEnvoyHealthCheckListener(ingressConfig v1beta1.IngressConfig, log l }, }, }, + SocketOptions: getKeepAliveSocketOptions(), } } @@ -236,6 +237,7 @@ 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), }, @@ -246,6 +248,7 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis return "" } listeners = append(listeners, &envoylistener.Listener{ + Address: &envoycore.Address{ Address: &envoycore.Address_SocketAddress{ SocketAddress: &envoycore.SocketAddress{ @@ -268,14 +271,18 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis }, }, }, + SocketOptions: getKeepAliveSocketOptions(), }) 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{ @@ -325,6 +332,7 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis // 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, @@ -358,6 +366,7 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis }, }, }, + SocketOptions: getKeepAliveSocketOptions(), }) // health-check http listener @@ -368,8 +377,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 +471,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, + }, + } +} From 450ebe71cdfac573f2a7606c0904c6b7257a7f8a Mon Sep 17 00:00:00 2001 From: Razvan Dobre Date: Thu, 17 Mar 2022 13:32:53 +0200 Subject: [PATCH 11/23] Enable envoy tls termination (#41) --- api/v1beta1/kafkacluster_types.go | 27 +- charts/kafka-operator/crds/kafkaclusters.yaml | 16 +- .../kafka.banzaicloud.io_kafkaclusters.yaml | 16 +- .../kafkacluster_controller_envoy_test.go | 579 ++++++++++++++++++ ...ontroller_externallistenerbindings_test.go | 49 ++ .../tests/kafkacluster_controller_test.go | 74 +++ .../kafka/opt/kafka/config/log4j.properties | 1 - pkg/resources/envoy/configmap.go | 210 +++++-- pkg/resources/envoy/deployment.go | 25 +- pkg/resources/envoy/service.go | 28 +- pkg/resources/istioingress/gateway.go | 2 +- pkg/resources/istioingress/meshgateway.go | 4 +- pkg/resources/istioingress/virtualservice.go | 4 +- pkg/resources/kafka/kafka.go | 12 +- .../nodeportexternalaccess/service.go | 2 +- 15 files changed, 965 insertions(+), 84 deletions(-) diff --git a/api/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index 6ec98efbc..938635bc1 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -16,6 +16,7 @@ package v1beta1 import ( "fmt" + "strconv" "strings" "emperror.dev/errors" @@ -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 diff --git a/charts/kafka-operator/crds/kafkaclusters.yaml b/charts/kafka-operator/crds/kafkaclusters.yaml index 6790cb5b0..fb5d829cb 100644 --- a/charts/kafka-operator/crds/kafkaclusters.yaml +++ b/charts/kafka-operator/crds/kafkaclusters.yaml @@ -17916,6 +17916,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) @@ -20180,6 +20184,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) @@ -21289,7 +21298,7 @@ spec: controller format: int32 maximum: 65535 - minimum: 0 + minimum: -1 type: integer externalTrafficPolicy: description: externalTrafficPolicy denotes if this Service @@ -21322,6 +21331,7 @@ spec: minimum: 1024 type: integer name: + pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21361,6 +21371,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, @@ -21407,6 +21420,7 @@ spec: format: int32 type: integer name: + pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes diff --git a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml index 6790cb5b0..fb5d829cb 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml @@ -17916,6 +17916,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) @@ -20180,6 +20184,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) @@ -21289,7 +21298,7 @@ spec: controller format: int32 maximum: 65535 - minimum: 0 + minimum: -1 type: integer externalTrafficPolicy: description: externalTrafficPolicy denotes if this Service @@ -21322,6 +21331,7 @@ spec: minimum: 1024 type: integer name: + pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes @@ -21361,6 +21371,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, @@ -21407,6 +21420,7 @@ spec: format: int32 type: integer name: + pattern: ^[a-z0-9\-]+ type: string serverSSLCertSecret: description: ServerSSLCertSecret is a reference to the Kubernetes diff --git a/controllers/tests/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 6fed15d9f..466167fa6 100644 --- a/controllers/tests/kafkacluster_controller_envoy_test.go +++ b/controllers/tests/kafkacluster_controller_envoy_test.go @@ -720,6 +720,269 @@ staticResources: 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.IntVal).To(BeEquivalentTo(29092)) + + 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(v1beta1.DefaultEnvoyHealthCheckPort)) + Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyHealthCheckPort)) + + 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(v1beta1.DefaultEnvoyAdminPort)) + Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyAdminPort)) + + 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: v1beta1.DefaultEnvoyAdminPort, + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-health", + ContainerPort: v1beta1.DefaultEnvoyHealthCheckPort, + 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: + - exactMatch: /healthcheck + name: :path + passThroughMode: false + - name: envoy.filters.http.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)) +} + func expectEnvoyWithConfigAz2(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster) { var loadBalancer corev1.Service lbName := fmt.Sprintf("envoy-loadbalancer-test-az2-%s", kafkaCluster.Name) @@ -1039,3 +1302,319 @@ staticResources: `, 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.IntVal).To(BeEquivalentTo(29092)) + + 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(v1beta1.DefaultEnvoyHealthCheckPort)) + Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyHealthCheckPort)) + + 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(v1beta1.DefaultEnvoyAdminPort)) + Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyAdminPort)) + + 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: v1beta1.DefaultEnvoyAdminPort, + Protocol: corev1.ProtocolTCP, + }, + corev1.ContainerPort{ + Name: "tcp-health", + ContainerPort: v1beta1.DefaultEnvoyHealthCheckPort, + 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: + - exactMatch: /healthcheck + name: :path + passThroughMode: false + - name: envoy.filters.http.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 31f96146c..9b7cbeecf 100644 --- a/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go +++ b/controllers/tests/kafkacluster_controller_externallistenerbindings_test.go @@ -116,6 +116,23 @@ func expectBrokerConfigmapForAz1ExternalListener(ctx context.Context, kafkaClust 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) { configMap := corev1.ConfigMap{} Eventually(ctx, func() error { @@ -147,3 +164,35 @@ func expectBrokerConfigmapForAz2ExternalListener(ctx context.Context, kafkaClust 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_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/docker/kafka/opt/kafka/config/log4j.properties b/docker/kafka/opt/kafka/config/log4j.properties index 73b58315f..c56208444 100644 --- a/docker/kafka/opt/kafka/config/log4j.properties +++ b/docker/kafka/opt/kafka/config/log4j.properties @@ -18,7 +18,6 @@ log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.immediateFlush=true log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c)%n diff --git a/pkg/resources/envoy/configmap.go b/pkg/resources/envoy/configmap.go index 31589f199..31d185909 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,10 @@ 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" envoytypes "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" "github.com/ghodss/yaml" @@ -207,6 +210,88 @@ func generateEnvoyHealthCheckListener(ingressConfig v1beta1.IngressConfig, log l } } +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 { @@ -225,6 +310,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) @@ -242,37 +331,23 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis 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, - }, - }, - }, - }, - }, - SocketOptions: getKeepAliveSocketOptions(), - }) + + brokerPort := elistener.GetBrokerPort(int32(brokerId)) + tempListeners[brokerPort] = append(tempListeners[brokerPort], filterChain) clusters = append(clusters, &envoycluster.Cluster{ Name: fmt.Sprintf("broker-%d", brokerId), @@ -327,7 +402,6 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis }) } } - // Create an any cast broker access point // TCP_Proxy filter configuration tcpProxy := &envoytcpproxy.TcpProxy{ @@ -338,36 +412,62 @@ func GenerateEnvoyConfig(kc *v1beta1.KafkaCluster, elistener v1beta1.ExternalLis 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, }, }, - }, - }, - SocketOptions: getKeepAliveSocketOptions(), - }) + } + } + listeners = append(listeners, newListener) + } // health-check http listener healthCheckListener := generateEnvoyHealthCheckListener(ingressConfig, log) 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/kafka.go b/pkg/resources/kafka/kafka.go index cd1ebb2f1..36d8b8d14 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -1165,9 +1165,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 +1201,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 +1275,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) } 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( From eea16abe88fcc753049ae5bb58ab9fec8565ac1c Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Thu, 23 Jun 2022 15:36:17 +0300 Subject: [PATCH 12/23] Envoy config generated by the operator is invalid in envoy 1.22 Added explicit typeconfig for envoy.filters.http.router ``` [2022-06-16 13:27:58.425][1][info][main] [source/server/server.cc:939] exiting Didn't find a registered implementation for 'envoy.filters.http.router' with type URL: '' ``` --- .../kafkacluster_controller_envoy_test.go | 58 ++++++++++++------- pkg/resources/envoy/configmap.go | 10 +++- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/controllers/tests/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 466167fa6..92f1db6dd 100644 --- a/controllers/tests/kafkacluster_controller_envoy_test.go +++ b/controllers/tests/kafkacluster_controller_envoy_test.go @@ -349,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: @@ -683,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: @@ -736,13 +740,13 @@ func expectEnvoyWithConfigAz1Tls(kafkaCluster *v1beta1.KafkaCluster) { 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(v1beta1.DefaultEnvoyHealthCheckPort)) - Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyHealthCheckPort)) + 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(v1beta1.DefaultEnvoyAdminPort)) - Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyAdminPort)) + 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) @@ -761,12 +765,12 @@ func expectEnvoyWithConfigAz1Tls(kafkaCluster *v1beta1.KafkaCluster) { }, corev1.ContainerPort{ Name: "tcp-admin", - ContainerPort: v1beta1.DefaultEnvoyAdminPort, + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), Protocol: corev1.ProtocolTCP, }, corev1.ContainerPort{ Name: "tcp-health", - ContainerPort: v1beta1.DefaultEnvoyHealthCheckPort, + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort(), Protocol: corev1.ProtocolTCP, }, )) @@ -950,10 +954,14 @@ 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: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router routeConfig: name: local virtualHosts: @@ -1266,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: @@ -1319,13 +1329,13 @@ func expectEnvoyWithConfigAz2Tls(kafkaCluster *v1beta1.KafkaCluster) { 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(v1beta1.DefaultEnvoyHealthCheckPort)) - Expect(loadBalancer.Spec.Ports[1].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyHealthCheckPort)) + 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(v1beta1.DefaultEnvoyAdminPort)) - Expect(loadBalancer.Spec.Ports[2].TargetPort.IntVal).To(BeEquivalentTo(v1beta1.DefaultEnvoyAdminPort)) + 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) @@ -1344,12 +1354,12 @@ func expectEnvoyWithConfigAz2Tls(kafkaCluster *v1beta1.KafkaCluster) { }, corev1.ContainerPort{ Name: "tcp-admin", - ContainerPort: v1beta1.DefaultEnvoyAdminPort, + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), Protocol: corev1.ProtocolTCP, }, corev1.ContainerPort{ Name: "tcp-health", - ContainerPort: v1beta1.DefaultEnvoyHealthCheckPort, + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), Protocol: corev1.ProtocolTCP, }, )) @@ -1586,10 +1596,14 @@ 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: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router routeConfig: name: local virtualHosts: diff --git a/pkg/resources/envoy/configmap.go b/pkg/resources/envoy/configmap.go index 31d185909..ee13b2347 100644 --- a/pkg/resources/envoy/configmap.go +++ b/pkg/resources/envoy/configmap.go @@ -32,6 +32,7 @@ import ( 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" @@ -102,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, + }, + }, }, }, }, From ecf32237f37f5f29fed75b12264ef39deebdf039 Mon Sep 17 00:00:00 2001 From: Adrian Coman Date: Thu, 11 Aug 2022 16:29:25 +0300 Subject: [PATCH 13/23] Added TaintedBrokersSelector to kafkaClusterSpec (#48) Co-authored-by: Adrian Muraru --- api/v1beta1/kafkacluster_types.go | 2 + api/v1beta1/zz_generated.deepcopy.go | 10 +++- charts/kafka-operator/crds/kafkaclusters.yaml | 45 +++++++++++++++ .../kafka.banzaicloud.io_kafkaclusters.yaml | 45 +++++++++++++++ pkg/resources/kafka/kafka.go | 57 +++++-------------- 5 files changed, 113 insertions(+), 46 deletions(-) diff --git a/api/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index 938635bc1..319473ae0 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -153,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"` diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index a3e79c9ca..07cb73477 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -23,8 +23,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 +845,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) @@ -1126,7 +1132,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/crds/kafkaclusters.yaml b/charts/kafka-operator/crds/kafkaclusters.yaml index fb5d829cb..e4e08c34a 100644 --- a/charts/kafka-operator/crds/kafkaclusters.yaml +++ b/charts/kafka-operator/crds/kafkaclusters.yaml @@ -21584,6 +21584,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_kafkaclusters.yaml b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml index fb5d829cb..e4e08c34a 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml @@ -21584,6 +21584,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/pkg/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index 36d8b8d14..5f1d3d3f5 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -23,12 +23,11 @@ import ( "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" @@ -861,11 +860,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 && @@ -983,53 +984,21 @@ 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 -} +// 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) -func (r *Reconciler) existsFailedBrokerFromAnotherRack(currentPodAz string, impactedReplicas map[int32]struct{}, kafkaBrokerAvailabilityZoneMap map[int32]string) bool { - if currentPodAz == "" && len(impactedReplicas) > 0 { - return true - } - for brokerWithFailure := range impactedReplicas { - if currentPodAz != kafkaBrokerAvailabilityZoneMap[brokerWithFailure] { - return true - } + if err != nil { + log.Error(err, "Invalid tainted brokers label selector") + return false } - return false -} -func (r *Reconciler) existsTerminatingPodFromAnotherAz(currentPodAz string, terminatingOrPendingPods []corev1.Pod, kafkaBrokerAvailabilityZoneMap map[int32]string) bool { - if currentPodAz == "" && len(terminatingOrPendingPods) > 0 { - return true - } - for _, terminatingOrPendingPod := range terminatingOrPendingPods { - terminatingOrPendingPodAz, err := r.getBrokerAz(&terminatingOrPendingPod, kafkaBrokerAvailabilityZoneMap) - if err != nil || currentPodAz != terminatingOrPendingPodAz { - return true - } + if selector.Empty() { + return false } - 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 From a40d5fe28b9bac5155aab04cd18bf8fdb03b67c5 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Mon, 15 May 2023 18:08:22 +0300 Subject: [PATCH 14/23] Remove disk feature (#53) * Implement disk removal feature --------- Co-authored-by: Alex Necula --- api/v1alpha1/common_types.go | 2 + api/v1alpha1/cruisecontroloperation_types.go | 10 +- api/v1beta1/common_types.go | 54 +- .../cruisecontroloperation_controller.go | 72 +- .../cruisecontroloperation_controller_test.go | 15 + controllers/cruisecontroltask_controller.go | 110 ++- .../cruisecontroltask_controller_test.go | 116 +++ controllers/cruisecontroltask_types.go | 26 +- controllers/kafkacluster_controller.go | 1 + .../cruisecontroloperation_controller_test.go | 102 ++- controllers/tests/mocks/scale.go | 15 + go.mod | 3 +- go.sum | 13 +- pkg/k8sutil/status.go | 53 +- pkg/resources/kafka/configmap.go | 31 +- pkg/resources/kafka/kafka.go | 81 +- pkg/resources/kafka/kafka_test.go | 810 +++++------------- pkg/scale/scale.go | 129 ++- pkg/scale/scale_test.go | 70 ++ pkg/scale/types.go | 1 + pkg/webhooks/kafkacluster_validator.go | 82 -- pkg/webhooks/kafkacluster_validator_test.go | 467 ---------- 22 files changed, 967 insertions(+), 1296 deletions(-) create mode 100644 pkg/scale/scale_test.go 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/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/controllers/cruisecontroloperation_controller.go b/controllers/cruisecontroloperation_controller.go index 9a5db907e..4fc5d445e 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") @@ -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 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..94a32ec44 100644 --- a/controllers/cruisecontroltask_controller_test.go +++ b/controllers/cruisecontroltask_controller_test.go @@ -15,9 +15,20 @@ package controllers import ( + "context" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "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 +306,108 @@ 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]) + }, + }, + } + + for _, testCase := range testCases { + mockClient := new(mocks.Client) + 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.On("Create", ctx, mock.IsType(&banzaiv1alpha1.CruiseControlOperation{})).Run(func(args mock.Arguments) { + createdOperation = args.Get(1).(*banzaiv1alpha1.CruiseControlOperation) + createdOperation.ObjectMeta.Name = "generated-name" + }).Return(nil) + + // Mock the Status call + mockClient.On("Status").Return(mockClient) + + // Mock the Update call + mockClient.On("Update", ctx, mock.IsType(&banzaiv1alpha1.CruiseControlOperation{})).Run(func(args mock.Arguments) { + arg := args.Get(1).(*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/tests/cruisecontroloperation_controller_test.go b/controllers/tests/cruisecontroloperation_controller_test.go index 67059a505..8fc6e877f 100644 --- a/controllers/tests/cruisecontroloperation_controller_test.go +++ b/controllers/tests/cruisecontroloperation_controller_test.go @@ -305,32 +305,58 @@ var _ = Describe("CruiseControlTaskReconciler", func() { }, 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()) - operation := generateCruiseControlOperation("add-broker-operation", namespace, kafkaCluster.GetName()) - err := k8sClient.Create(ctx, &operation) + When("there is an errored remove_disks and a rebalance disks operation for the same broker", Serial, func() { + JustBeforeEach(func() { + cruiseControlOperationReconciler.ScaleFactory = 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.OperationAddBroker, - ID: "11111", + 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(ctx, &operation) + 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 create status CruiseControlOperation and retry", func(ctx SpecContext) { - Eventually(ctx, func() v1beta1.CruiseControlUserTaskState { - operation := v1alpha1.CruiseControlOperation{} - err := k8sClient.Get(ctx, client.ObjectKey{ + 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: "add-broker-operation", - }, &operation) + Name: opName1, + }, &removeDisksOp) if err != nil { - return "" + return false } - return operation.CurrentTaskState() - }, 15*time.Second, 500*time.Millisecond).Should(Equal(v1beta1.CruiseControlTaskCompleted)) + 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()) }) }) }) @@ -489,36 +515,34 @@ func getScaleMock5() *mocks.MockCruiseControlScaler { return scaleMock } -func getScaleMock7() *mocks.MockCruiseControlScaler { +func getScaleMock6() *mocks.MockCruiseControlScaler { mockCtrl := gomock.NewController(GinkgoT()) scaleMock := mocks.NewMockCruiseControlScaler(mockCtrl) scaleMock.EXPECT().IsUp(gomock.Any()).Return(true).AnyTimes() - startTime := metav1.Now().Format(time.RFC1123) - scaleMock.EXPECT().Status(gomock.Any()).Return(scale.StatusTaskResult{ - TaskResult: &scale.Result{ - TaskID: "22222", - StartedAt: startTime, - State: v1beta1.CruiseControlTaskActive, - }}, nil).AnyTimes() - scaleMock.EXPECT().StatusTask(gomock.Any(), "22222").Return(scale.StatusTaskResult{ - TaskResult: &scale.Result{ - TaskID: "22222", - StartedAt: startTime, - State: v1beta1.CruiseControlTaskCompleted, - }, - Status: &scale.CruiseControlStatus{ - ExecutorReady: true, - MonitorReady: true, - AnalyzerReady: true, - }}, nil).AnyTimes() - userTaskResult := []*scale.Result{scaleResultPointer(scale.Result{ - TaskID: "11111", + TaskID: "12345", StartedAt: "Sat, 27 Aug 2022 12:22:21 GMT", - State: v1beta1.CruiseControlTaskCompleted, + State: v1beta1.CruiseControlTaskCompletedWithError, })} scaleMock.EXPECT().UserTasks(gomock.Any(), gomock.Any()).Return(userTaskResult, nil).AnyTimes() + scaleMock.EXPECT().Status(gomock.Any()).Return(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 } diff --git a/controllers/tests/mocks/scale.go b/controllers/tests/mocks/scale.go index 9fb0fd29e..23ec7cdb7 100644 --- a/controllers/tests/mocks/scale.go +++ b/controllers/tests/mocks/scale.go @@ -52,6 +52,21 @@ func (m *MockCruiseControlScaler) EXPECT() *MockCruiseControlScalerMockRecorder return m.recorder } +// 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) +} + // AddBrokers mocks base method. func (m *MockCruiseControlScaler) AddBrokers(ctx context.Context, brokerIDs ...string) (*scale.Result, error) { m.ctrl.T.Helper() diff --git a/go.mod b/go.mod index 9a7581506..595ec1960 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( 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 + golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea google.golang.org/protobuf v1.28.1 gopkg.in/inf.v0 v0.9.1 gotest.tools v2.2.0+incompatible @@ -137,6 +137,7 @@ require ( ) replace ( + github.com/banzaicloud/go-cruise-control => github.com/adobe/go-cruise-control v0.6.0-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 diff --git a/go.sum b/go.sum index af972fd8d..b183b33f3 100644 --- a/go.sum +++ b/go.sum @@ -50,14 +50,19 @@ 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/adobe/go-cruise-control v0.6.0-adbe h1:Qr9NJ4clpbgNmZQK52b96fg+7+wnrjNRF7i7upHLUk0= +github.com/adobe/go-cruise-control v0.6.0-adbe/go.mod h1:52C8XiTZjSmFVD+y76rd2al//GTJk9mSwkcHs2LGSvA= +github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= 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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= 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= @@ -503,8 +508,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-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= +golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= 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= diff --git a/pkg/k8sutil/status.go b/pkg/k8sutil/status.go index fe6713b56..5ba4a68a8 100644 --- a/pkg/k8sutil/status.go +++ b/pkg/k8sutil/status.go @@ -179,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 @@ -224,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 diff --git a/pkg/resources/kafka/configmap.go b/pkg/resources/kafka/configmap.go index 4c00eabf0..3c900e7cd 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") } } diff --git a/pkg/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index 5f1d3d3f5..95090480e 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -574,7 +574,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]) } @@ -999,9 +999,11 @@ func (r *Reconciler) isPodTainted(log logr.Logger, pod *corev1.Pod) bool { 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{}) @@ -1018,6 +1020,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") @@ -1048,8 +1111,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 @@ -1104,6 +1169,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 } @@ -1117,10 +1186,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) } } diff --git a/pkg/resources/kafka/kafka_test.go b/pkg/resources/kafka/kafka_test.go index 23d5e4be8..df23eff3a 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -18,30 +18,24 @@ import ( "context" "reflect" "testing" - "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" + "github.com/stretchr/testify/mock" "go.uber.org/mock/gomock" "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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "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) { @@ -959,653 +953,277 @@ func TestGetServerPasswordKeysAndUsers(t *testing.T) { //nolint funlen } } -// nolint funlen -func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { +func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { t.Parallel() testCases := []struct { - testName string - kafkaCluster v1beta1.KafkaCluster - desiredPod *corev1.Pod - currentPod *corev1.Pod - pods []corev1.Pod - allOfflineReplicas []int32 - outOfSyncReplicas []int32 - ccStatus *scale.StatusTaskResult - errorExpected bool + 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: "Pod is not deleted if pod list count different from spec", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, - }, - Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, - }, - desiredPod: &corev1.Pod{}, - currentPod: &corev1.Pod{}, - pods: []corev1.Pod{}, - errorExpected: true, - }, - { - testName: "Pod is not deleted if allowed concurrent restarts not specified (default=1) and another pod is restarting", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, + 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"), }, - Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, }, - 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"}}, + existingPvcs: []*corev1.PersistentVolumeClaim{ + createPvc("test-pvc-1", "0", "/path/to/mount1"), + createPvc("test-pvc-2", "0", "/path/to/mount2"), }, - errorExpected: true, + kafkaClusterStatus: v1beta1.KafkaClusterStatus{}, + expectedError: false, + expectedDeletePvc: false, + expectedVolumeState: nil, }, { - testName: "Pod is not deleted if allowed concurrent restarts equals pods restarting", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - ConcurrentBrokerRestartCountPerRack: 2, + 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, + }, + }, + }, }, }, - Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, }, - 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"}}, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRemovalRequired, }, - errorExpected: true, }, { - testName: "Pod is not deleted if broker.rack is not set in all read-only configs, if another pod is restarting", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{{Id: 101}, {Id: 102}, {Id: 201}, {Id: 102}, {Id: 301}, {Id: 302}}, - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {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"}}}, - }, - 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{}}}, + 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, + }, + }, + }, }, }, }, - errorExpected: true, - }, - { - testName: "Pod is not deleted if broker.rack is not set in some read-only configs, if another pod is restarting", - 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: ""}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 202, ReadOnlyConfig: ""}, - {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, - {Id: 302, ReadOnlyConfig: ""}}, - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {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"}}}, - }, - 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{}}}, - }, - }, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRebalanceScheduled, }, - errorExpected: true, - }, - { - testName: "Pod is not deleted if allowed concurrent restarts is not specified and failure threshold is 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: 1, - }, - }, - 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"}}}, - }, - errorExpected: true, - }, - { - testName: "Pod is deleted if allowed concurrent restarts is default and failure threshold 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: 1, - ConcurrentBrokerRestartCountPerRack: 1, - }, - }, - 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{}, - errorExpected: false, }, { - testName: "Pod is not deleted if pod is restarting in another AZ, even if 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-201", Labels: map[string]string{"brokerId": "201"}}}, - pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {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"}}}, - }, - 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{}}}, + 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, + }, + }, + }, }, }, }, - errorExpected: true, - }, - { - testName: "Pod is not deleted if failure is in another AZ, even if 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-101", Labels: map[string]string{"brokerId": "101"}}}, - 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{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, - }, - { - testName: "Pod is deleted if failure is in same AZ 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, - {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}, - 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{}}}, - }, - }, + expectedError: true, + expectedDeletePvc: false, + expectedVolumeState: map[string]v1beta1.CruiseControlVolumeState{ + "/path/to/mount2": v1beta1.GracefulDiskRemovalRunning, }, - errorExpected: false, }, { - testName: "Pod is not deleted if pod is restarting in another AZ, if brokers per AZ < tolerated failures", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, 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-201", Labels: map[string]string{"brokerId": "201"}}}, - pods: []corev1.Pod{ - {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"}}}, - }, - 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{}}}, + 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, + }, + }, + }, }, }, }, - errorExpected: true, + expectedError: false, + expectedDeletePvc: true, + expectedVolumeState: nil, }, { - testName: "Pod is not deleted if there are out-of-sync replicas in another AZ, if brokers per AZ < tolerated failures", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, 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-201", Labels: map[string]string{"brokerId": "201"}}}, - pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, - {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}, - errorExpected: true, - }, - { - testName: "Pod is not deleted if there are offline replicas in another AZ, if brokers per AZ < tolerated failures", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, - {Id: 301, 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-201", Labels: map[string]string{"brokerId": "201"}}}, - pods: []corev1.Pod{ - {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, - {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{101}, - outOfSyncReplicas: []int32{}, - errorExpected: true, - }, - { - testName: "Pod is not deleted if pod is restarting in another AZ, if broker rack value contains dashes", - kafkaCluster: v1beta1.KafkaCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "kafka", - Namespace: "kafka", - }, - Spec: v1beta1.KafkaClusterSpec{ - Brokers: []v1beta1.Broker{ - {Id: 101, ReadOnlyConfig: "broker.rack=az-1"}, - {Id: 201, ReadOnlyConfig: "broker.rack=az-2"}, - {Id: 301, ReadOnlyConfig: "broker.rack=az-3"}, - }, - RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ - FailureThreshold: 2, - ConcurrentBrokerRestartCountPerRack: 2, - }, - }, - Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, - }, - desiredPod: &corev1.Pod{}, - currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, - pods: []corev1.Pod{ - {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"}}}, - }, - 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{}}}, + 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, + }, + }, + }, }, }, }, - errorExpected: true, + 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) - mockKafkaClientProvider := new(kafkaclient.MockedProvider) - + mockClient := new(mocks.Client) t.Run(test.testName, func(t *testing.T) { - r := New(mockClient, nil, &test.kafkaCluster, mockKafkaClientProvider) + r := Reconciler{ + Reconciler: resources.Reconciler{ + Client: mockClient, + KafkaCluster: &v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + }, + }, + } - // Mock client - mockClient.EXPECT().List( + // Set up the mockClient to return the provided test.existingPvcs + mockClient.On( + "List", context.TODO(), - gomock.AssignableToTypeOf(&corev1.PodList{}), + mock.IsType(&corev1.PersistentVolumeClaimList{}), client.InNamespace("kafka"), - gomock.Any(), - ).Do(func(ctx context.Context, list *corev1.PodList, opts ...client.ListOption) { - list.Items = test.pods + mock.AnythingOfType("client.MatchingLabels"), + ).Run(func(args mock.Arguments) { + arg := args.Get(1).(*corev1.PersistentVolumeClaimList) + + // Convert []*corev1.PersistentVolumeClaim to []corev1.PersistentVolumeClaim + pvcItems := make([]corev1.PersistentVolumeClaim, len(test.existingPvcs)) + for i, pvc := range test.existingPvcs { + pvcItems[i] = *pvc + } + + arg.Items = pvcItems }).Return(nil) - if !test.errorExpected { - mockClient.EXPECT().Delete(context.TODO(), test.currentPod).Return(nil) - } - // Mock kafka client - mockedKafkaClient := mocks.NewMockKafkaClient(mockCtrl) - if test.allOfflineReplicas != nil { - mockedKafkaClient.EXPECT().AllOfflineReplicas().Return(test.allOfflineReplicas, nil) - } - if test.outOfSyncReplicas != nil { - mockedKafkaClient.EXPECT().OutOfSyncReplicas().Return(test.outOfSyncReplicas, nil) - } - mockKafkaClientProvider.On("NewFromCluster", mockClient, &test.kafkaCluster).Return(mockedKafkaClient, func() {}, nil) + // Mock the client.Delete call + mockClient.On("Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")).Return(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) + // Mock the status update call + mockClient.On("Status").Return(mockClient) + mockClient.On("Update", context.TODO(), mock.AnythingOfType("*v1beta1.KafkaCluster")).Run(func(args mock.Arguments) { + arg := args.Get(1).(*v1beta1.KafkaCluster) + r.KafkaCluster.Status = arg.Status + }).Return(nil) + + // Set up the r.KafkaCluster.Status with the provided test.kafkaClusterStatus + r.KafkaCluster.Status = test.kafkaClusterStatus - // 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)) + // 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.errorExpected { + if test.expectedError { assert.NotNil(t, err, "Expected an error but got nil") } else { - assert.Nil(t, err, "Expected no error but got one") + assert.Nil(t, err, "Expected no error but got an error") + } + + // Test that PVC is deleted if expected + if test.expectedDeletePvc { + mockClient.AssertCalled(t, "Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")) + } else { + mockClient.AssertNotCalled(t, "Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")) + } + + // 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) + } } }) } } -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"}, - }, - }, +//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, }, - 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"}, - }, - }, + Annotations: map[string]string{ + "mountPath": mountPath, }, - 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", - }, + Status: corev1.PersistentVolumeClaimStatus{ + Phase: corev1.ClaimBound, }, } - - 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/scale/scale.go b/pkg/scale/scale.go index 90afd7ff5..403383b99 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: {}, } ) @@ -291,19 +295,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 +372,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 +554,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 +606,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..ae1311acb 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) diff --git a/pkg/webhooks/kafkacluster_validator.go b/pkg/webhooks/kafkacluster_validator.go index f3395b731..d2d8a6b41 100644 --- a/pkg/webhooks/kafkacluster_validator.go +++ b/pkg/webhooks/kafkacluster_validator.go @@ -18,8 +18,6 @@ import ( "context" "fmt" - "emperror.dev/errors" - "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -37,19 +35,9 @@ type KafkaClusterValidator struct { func (s KafkaClusterValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) 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...) @@ -89,76 +77,6 @@ func (s KafkaClusterValidator) ValidateDelete(ctx context.Context, obj runtime.O 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 - } - } - } - } - } - 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 { var allErrs field.ErrorList 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 From f023d28f549d01b5b8e7becf8bfee9145656d708 Mon Sep 17 00:00:00 2001 From: aguzovatii Date: Tue, 16 May 2023 14:50:55 +0300 Subject: [PATCH 15/23] Handle async response from CC /state endpoint (#56) * Handle the case when the request to CC STATE endpoint returns the async task instead of the result When the request on /state endpoint of CC takes longer than webserver.request.maxBlockTimeMs, then CC will convert the request into an async task and will respond with the taskID instead of the result. The Koperator should handle this case by waiting for CC to complete the task. --- .../cruisecontroloperation_controller.go | 7 +- .../cruisecontroloperation_controller_test.go | 72 +++++++++++++++++-- controllers/tests/mocks/scale.go | 30 ++++---- pkg/scale/scale.go | 5 +- pkg/scale/types.go | 1 - 5 files changed, 88 insertions(+), 27 deletions(-) diff --git a/controllers/cruisecontroloperation_controller.go b/controllers/cruisecontroloperation_controller.go index 4fc5d445e..56eaedb1c 100644 --- a/controllers/cruisecontroloperation_controller.go +++ b/controllers/cruisecontroloperation_controller.go @@ -154,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) @@ -525,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 @@ -533,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/tests/cruisecontroloperation_controller_test.go b/controllers/tests/cruisecontroloperation_controller_test.go index 8fc6e877f..458637d55 100644 --- a/controllers/tests/cruisecontroloperation_controller_test.go +++ b/controllers/tests/cruisecontroloperation_controller_test.go @@ -359,6 +359,34 @@ var _ = Describe("CruiseControlTaskReconciler", func() { }, 10*time.Second, 500*time.Millisecond).Should(BeTrue()) }) }) + When("Cruise Control makes the Status operation async", Serial, func() { + JustBeforeEach(func(ctx SpecContext) { + cruiseControlOperationReconciler.ScaleFactory = NewMockScaleFactory(getScaleMock7()) + operation := generateCruiseControlOperation("add-broker-operation", namespace, kafkaCluster.GetName()) + err := k8sClient.Create(ctx, &operation) + Expect(err).NotTo(HaveOccurred()) + + operation.Status.CurrentTask = &v1alpha1.CruiseControlTask{ + Operation: v1alpha1.OperationAddBroker, + ID: "11111", + } + err = k8sClient.Status().Update(ctx, &operation) + Expect(err).NotTo(HaveOccurred()) + }) + It("should create status CruiseControlOperation and retry", func(ctx SpecContext) { + Eventually(ctx, func() v1beta1.CruiseControlUserTaskState { + operation := v1alpha1.CruiseControlOperation{} + err := k8sClient.Get(ctx, client.ObjectKey{ + Namespace: kafkaCluster.Namespace, + Name: "add-broker-operation", + }, &operation) + if err != nil { + return "" + } + return operation.CurrentTaskState() + }, 15*time.Second, 500*time.Millisecond).Should(Equal(v1beta1.CruiseControlTaskCompleted)) + }) + }) }) func generateCruiseControlOperation(name, namespace, kafkaRef string) v1alpha1.CruiseControlOperation { @@ -526,11 +554,12 @@ func getScaleMock6() *mocks.MockCruiseControlScaler { State: v1beta1.CruiseControlTaskCompletedWithError, })} scaleMock.EXPECT().UserTasks(gomock.Any(), gomock.Any()).Return(userTaskResult, nil).AnyTimes() - scaleMock.EXPECT().Status(gomock.Any()).Return(scale.CruiseControlStatus{ - ExecutorReady: true, - MonitorReady: true, - AnalyzerReady: true, - }, 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", @@ -546,6 +575,39 @@ func getScaleMock6() *mocks.MockCruiseControlScaler { return scaleMock } +func getScaleMock7() *mocks.MockCruiseControlScaler { + mockCtrl := gomock.NewController(GinkgoT()) + scaleMock := mocks.NewMockCruiseControlScaler(mockCtrl) + scaleMock.EXPECT().IsUp(gomock.Any()).Return(true).AnyTimes() + + startTime := metav1.Now().Format(time.RFC1123) + scaleMock.EXPECT().Status(gomock.Any()).Return(scale.StatusTaskResult{ + TaskResult: &scale.Result{ + TaskID: "22222", + StartedAt: startTime, + State: v1beta1.CruiseControlTaskActive, + }}, nil).AnyTimes() + scaleMock.EXPECT().StatusTask(gomock.Any(), "22222").Return(scale.StatusTaskResult{ + TaskResult: &scale.Result{ + TaskID: "22222", + StartedAt: startTime, + State: v1beta1.CruiseControlTaskCompleted, + }, + Status: &scale.CruiseControlStatus{ + ExecutorReady: true, + MonitorReady: true, + AnalyzerReady: true, + }}, nil).AnyTimes() + + userTaskResult := []*scale.Result{scaleResultPointer(scale.Result{ + TaskID: "11111", + StartedAt: "Sat, 27 Aug 2022 12:22:21 GMT", + State: v1beta1.CruiseControlTaskCompleted, + })} + scaleMock.EXPECT().UserTasks(gomock.Any(), gomock.Any()).Return(userTaskResult, nil).AnyTimes() + return scaleMock +} + func scaleResultPointer(res scale.Result) *scale.Result { return &res } diff --git a/controllers/tests/mocks/scale.go b/controllers/tests/mocks/scale.go index 23ec7cdb7..e5a6057ba 100644 --- a/controllers/tests/mocks/scale.go +++ b/controllers/tests/mocks/scale.go @@ -52,21 +52,6 @@ func (m *MockCruiseControlScaler) EXPECT() *MockCruiseControlScalerMockRecorder return m.recorder } -// 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) -} - // AddBrokers mocks base method. func (m *MockCruiseControlScaler) AddBrokers(ctx context.Context, brokerIDs ...string) (*scale.Result, error) { m.ctrl.T.Helper() @@ -295,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/pkg/scale/scale.go b/pkg/scale/scale.go index 403383b99..cb71fd4f1 100644 --- a/pkg/scale/scale.go +++ b/pkg/scale/scale.go @@ -125,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 } @@ -138,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 } diff --git a/pkg/scale/types.go b/pkg/scale/types.go index ae1311acb..92b9d8f63 100644 --- a/pkg/scale/types.go +++ b/pkg/scale/types.go @@ -65,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. From 514fa07bccf06325955be0e4e4b8ebb6274776b3 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Sat, 10 Jun 2023 19:31:58 +0300 Subject: [PATCH 16/23] Allow concurrent broker restarts from same AZ (broker rack) (#62) --- api/go.mod | 2 + api/v1beta1/kafkacluster_types.go | 8 +- charts/kafka-operator/crds/kafkaclusters.yaml | 10 +- .../kafka.banzaicloud.io_kafkaclusters.yaml | 10 +- .../cruisecontroltask_controller_test.go | 18 +- controllers/tests/common_test.go | 2 +- .../cruisecontroloperation_controller_test.go | 4 +- go.mod | 21 +- go.sum | 44 +- pkg/resources/kafka/configmap_test.go | 1 - pkg/resources/kafka/kafka.go | 100 +++-- pkg/resources/kafka/kafka_test.go | 396 ++++++++++++++++-- .../kafka/mocks/SubResourceClient.go | 122 ++++++ properties/go.mod | 2 + 14 files changed, 625 insertions(+), 115 deletions(-) create mode 100644 pkg/resources/kafka/mocks/SubResourceClient.go diff --git a/api/go.mod b/api/go.mod index 55a13bb52..6a78be27a 100644 --- a/api/go.mod +++ b/api/go.mod @@ -34,3 +34,5 @@ require ( sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // 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/v1beta1/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index 319473ae0..be017c77d 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -214,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 diff --git a/charts/kafka-operator/crds/kafkaclusters.yaml b/charts/kafka-operator/crds/kafkaclusters.yaml index e4e08c34a..5c4296aff 100644 --- a/charts/kafka-operator/crds/kafkaclusters.yaml +++ b/charts/kafka-operator/crds/kafkaclusters.yaml @@ -21556,10 +21556,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 @@ -21570,8 +21569,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 diff --git a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml index e4e08c34a..5c4296aff 100644 --- a/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml +++ b/config/base/crds/kafka.banzaicloud.io_kafkaclusters.yaml @@ -21556,10 +21556,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 @@ -21570,8 +21569,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 diff --git a/controllers/cruisecontroltask_controller_test.go b/controllers/cruisecontroltask_controller_test.go index 94a32ec44..bc0f9f012 100644 --- a/controllers/cruisecontroltask_controller_test.go +++ b/controllers/cruisecontroltask_controller_test.go @@ -19,10 +19,11 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" + "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" @@ -370,8 +371,11 @@ func TestCreateCCOperation(t *testing.T) { }, } + mockCtrl := gomock.NewController(t) + for _, testCase := range testCases { - mockClient := new(mocks.Client) + mockClient := mocks.NewMockClient(mockCtrl) + mockSubResourceClient := mocks.NewMockSubResourceClient(mockCtrl) scheme := runtime.NewScheme() _ = v1beta1.AddToScheme(scheme) _ = corev1.AddToScheme(scheme) @@ -389,17 +393,17 @@ func TestCreateCCOperation(t *testing.T) { // Mock the Create call and capture the operation var createdOperation *banzaiv1alpha1.CruiseControlOperation - mockClient.On("Create", ctx, mock.IsType(&banzaiv1alpha1.CruiseControlOperation{})).Run(func(args mock.Arguments) { - createdOperation = args.Get(1).(*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.On("Status").Return(mockClient) + mockClient.EXPECT().Status().Return(mockSubResourceClient) // Mock the Update call - mockClient.On("Update", ctx, mock.IsType(&banzaiv1alpha1.CruiseControlOperation{})).Run(func(args mock.Arguments) { - arg := args.Get(1).(*banzaiv1alpha1.CruiseControlOperation) + 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) diff --git a/controllers/tests/common_test.go b/controllers/tests/common_test.go index 12931a799..0a92b14d2 100644 --- a/controllers/tests/common_test.go +++ b/controllers/tests/common_test.go @@ -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}, }, } } diff --git a/controllers/tests/cruisecontroloperation_controller_test.go b/controllers/tests/cruisecontroloperation_controller_test.go index 458637d55..ba1b1c823 100644 --- a/controllers/tests/cruisecontroloperation_controller_test.go +++ b/controllers/tests/cruisecontroloperation_controller_test.go @@ -307,7 +307,7 @@ var _ = Describe("CruiseControlTaskReconciler", func() { }) When("there is an errored remove_disks and a rebalance disks operation for the same broker", Serial, func() { JustBeforeEach(func() { - cruiseControlOperationReconciler.ScaleFactory = NewMockScaleFactory(getScaleMock6()) + cruiseControlOperationReconciler.ScaleFactory = mocks.NewMockScaleFactory(getScaleMock6()) // Remove_disk operation - errored operation := generateCruiseControlOperation(opName1, namespace, kafkaCluster.GetName()) err := k8sClient.Create(context.Background(), &operation) @@ -361,7 +361,7 @@ var _ = Describe("CruiseControlTaskReconciler", func() { }) When("Cruise Control makes the Status operation async", Serial, func() { JustBeforeEach(func(ctx SpecContext) { - cruiseControlOperationReconciler.ScaleFactory = NewMockScaleFactory(getScaleMock7()) + cruiseControlOperationReconciler.ScaleFactory = mocks.NewMockScaleFactory(getScaleMock7()) operation := generateCruiseControlOperation("add-broker-operation", namespace, kafkaCluster.GetName()) err := k8sClient.Create(ctx, &operation) Expect(err).NotTo(HaveOccurred()) diff --git a/go.mod b/go.mod index 595ec1960..401d1f2fd 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,14 @@ require ( 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/onsi/ginkgo/v2 v2.9.7 + github.com/onsi/gomega v1.27.8 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-20230510235704-dd950f8aeaea + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 google.golang.org/protobuf v1.28.1 gopkg.in/inf.v0 v0.9.1 gotest.tools v2.2.0+incompatible @@ -40,7 +40,7 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/stretchr/objx v0.5.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/tools v0.9.1 // indirect ) require ( @@ -113,12 +113,12 @@ require ( 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/crypto v0.5.0 // indirect + golang.org/x/net v0.10.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 + 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 gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -143,3 +143,6 @@ replace ( 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 ) + +// 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/go.sum b/go.sum index b183b33f3..7dbd0a3c1 100644 --- a/go.sum +++ b/go.sum @@ -52,17 +52,12 @@ github.com/Shopify/toxiproxy/v2 v2.4.0 h1:O1e4Jfvr/hefNTNu+8VtdEG5lSeamJRo4aKhMO github.com/Shopify/toxiproxy/v2 v2.4.0/go.mod h1:3ilnjng821bkozDRxNoo64oI/DKqM+rOyJzb564+bvg= github.com/adobe/go-cruise-control v0.6.0-adbe h1:Qr9NJ4clpbgNmZQK52b96fg+7+wnrjNRF7i7upHLUk0= github.com/adobe/go-cruise-control v0.6.0-adbe/go.mod h1:52C8XiTZjSmFVD+y76rd2al//GTJk9mSwkcHs2LGSvA= -github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= 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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= 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= @@ -360,12 +355,12 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB 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.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= 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/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= 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= @@ -496,8 +491,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh 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.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= 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= @@ -508,8 +503,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-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -534,6 +529,7 @@ 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.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= 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= @@ -577,8 +573,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug 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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 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= @@ -601,7 +597,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ 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.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= 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= @@ -657,13 +653,13 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc 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.6.0/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/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/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 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= @@ -673,8 +669,8 @@ 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/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.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= @@ -726,8 +722,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc 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.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/resources/kafka/configmap_test.go b/pkg/resources/kafka/configmap_test.go index 3890e7fcc..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, diff --git a/pkg/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index 95090480e..97511d6df 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -18,6 +18,7 @@ import ( "context" "fmt" "reflect" + "regexp" "sort" "strconv" "strings" @@ -32,8 +33,6 @@ import ( "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" @@ -90,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 @@ -107,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 @@ -132,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, @@ -902,25 +920,18 @@ 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) >= concurrentBrokerRestartsAllowed { + return errorfactory.New(errorfactory.ReconcileRollingUpgrade{}, errors.New(strconv.Itoa(concurrentBrokerRestartsAllowed)+" pod(s) is still terminating or creating"), "rolling upgrade in progress") } - if r.KafkaCluster.Spec.RollingUpgradeConfig.ConcurrentBrokerRestartCountPerRack > 1 && len(terminatingOrPendingPods) > 0 { - err = r.checkCCRackAwareDistributionGoal() - if err != nil { - return err - } - } - 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") } @@ -958,8 +969,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") } } @@ -984,6 +995,37 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo return nil } +func (r *Reconciler) existsFailedBrokerFromAnotherRack(currentPodAz string, impactedReplicas map[int32]struct{}) bool { + if currentPodAz == "" && len(impactedReplicas) > 0 { + return true + } + for brokerWithFailure := range impactedReplicas { + if currentPodAz != r.kafkaBrokerAvailabilityZoneMap[brokerWithFailure] { + return true + } + } + return false +} + +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 { + 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) @@ -1436,12 +1478,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 df23eff3a..2843ec5fe 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -16,18 +16,20 @@ package kafka import ( "context" + "go.uber.org/mock/gomock" "reflect" "testing" + "time" "emperror.dev/errors" "github.com/go-logr/logr" "github.com/onsi/gomega" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "go.uber.org/mock/gomock" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/banzaicloud/koperator/pkg/kafkaclient" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -1133,8 +1135,11 @@ func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { }, } + mockCtrl := gomock.NewController(t) + for _, test := range testCases { - mockClient := new(mocks.Client) + mockClient := mocks.NewMockClient(mockCtrl) + mockSubResourceClient := mocks.NewMockSubResourceClient(mockCtrl) t.Run(test.testName, func(t *testing.T) { r := Reconciler{ Reconciler: resources.Reconciler{ @@ -1149,33 +1154,31 @@ func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { } // Set up the mockClient to return the provided test.existingPvcs - mockClient.On( - "List", + mockClient.EXPECT().List( context.TODO(), - mock.IsType(&corev1.PersistentVolumeClaimList{}), + gomock.AssignableToTypeOf(&corev1.PersistentVolumeClaimList{}), client.InNamespace("kafka"), - mock.AnythingOfType("client.MatchingLabels"), - ).Run(func(args mock.Arguments) { - arg := args.Get(1).(*corev1.PersistentVolumeClaimList) - + 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 } - arg.Items = pvcItems - }).Return(nil) + list.Items = pvcItems + }).Return(nil).AnyTimes() // Mock the client.Delete call - mockClient.On("Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")).Return(nil) + if test.expectedDeletePvc { + mockClient.EXPECT().Delete(context.TODO(), gomock.AssignableToTypeOf(&corev1.PersistentVolumeClaim{})).Return(nil) + } // Mock the status update call - mockClient.On("Status").Return(mockClient) - mockClient.On("Update", context.TODO(), mock.AnythingOfType("*v1beta1.KafkaCluster")).Run(func(args mock.Arguments) { - arg := args.Get(1).(*v1beta1.KafkaCluster) - r.KafkaCluster.Status = arg.Status - }).Return(nil) + mockClient.EXPECT().Status().Return(mockSubResourceClient).AnyTimes() + mockSubResourceClient.EXPECT().Update(context.TODO(), 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 @@ -1190,13 +1193,6 @@ func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { assert.Nil(t, err, "Expected no error but got an error") } - // Test that PVC is deleted if expected - if test.expectedDeletePvc { - mockClient.AssertCalled(t, "Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")) - } else { - mockClient.AssertNotCalled(t, "Delete", context.TODO(), mock.AnythingOfType("*v1.PersistentVolumeClaim")) - } - // Test that the expected volume state is set brokerState := r.KafkaCluster.Status.BrokersState["0"] if test.expectedVolumeState != nil { @@ -1227,3 +1223,353 @@ func createPvc(name, brokerId, mountPath string) *corev1.PersistentVolumeClaim { }, } } + +// nolint funlen +func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { + t.Parallel() + testCases := []struct { + testName string + kafkaCluster v1beta1.KafkaCluster + desiredPod *corev1.Pod + currentPod *corev1.Pod + pods []corev1.Pod + allOfflineReplicas []int32 + outOfSyncReplicas []int32 + errorExpected bool + }{ + { + testName: "Pod is not deleted if pod list count different from spec", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{}, + pods: []corev1.Pod{}, + errorExpected: true, + }, + { + testName: "Pod is not deleted if allowed concurrent restarts not specified (default=1) and another pod is restarting", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + 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"}}, + }, + errorExpected: true, + }, + { + testName: "Pod is not deleted if allowed concurrent restarts equals pods restarting", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{{Id: 101}, {Id: 201}, {Id: 301}}, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + 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"}}, + }, + errorExpected: true, + }, + { + testName: "Pod is not deleted if broker.rack is not set in all read-only configs, if another pod is restarting", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{{Id: 101}, {Id: 102}, {Id: 201}, {Id: 102}, {Id: 301}, {Id: 302}}, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + ConcurrentBrokerRestartsAllowed: 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {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"}}}, + }, + errorExpected: true, + }, + { + testName: "Pod is not deleted if broker.rack is not set in some read-only configs, if another pod is restarting", + 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: ""}, + {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, + {Id: 202, ReadOnlyConfig: ""}, + {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, + {Id: 302, ReadOnlyConfig: ""}}, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + ConcurrentBrokerRestartsAllowed: 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {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"}}}, + }, + errorExpected: true, + }, + { + testName: "Pod is not deleted if allowed concurrent restarts is not specified and failure threshold is 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: 1, + }, + }, + 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"}}}, + }, + outOfSyncReplicas: []int32{101}, + errorExpected: true, + }, + { + 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", + 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: 1, + }, + }, + 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"}}}, + }, + errorExpected: false, + }, + { + testName: "Pod is not deleted if pod is restarting in another AZ, even if 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, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + pods: []corev1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {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"}}}, + }, + outOfSyncReplicas: []int32{201}, + errorExpected: true, + }, + { + testName: "Pod is not deleted if failure is in another AZ, even if 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, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, + 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"}}}, + }, + outOfSyncReplicas: []int32{201}, + errorExpected: true, + }, + { + testName: "Pod is deleted if failure is in same AZ 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, + ConcurrentBrokerRestartsAllowed: 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"}, DeletionTimestamp: &metav1.Time{Time: time.Now()}}}, + {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"}}}, + }, + outOfSyncReplicas: []int32{101}, + errorExpected: false, + }, + } + + mockCtrl := gomock.NewController(t) + + for _, test := range testCases { + mockClient := mocks.NewMockClient(mockCtrl) + mockKafkaClientProvider := new(kafkaclient.MockedProvider) + + t.Run(test.testName, func(t *testing.T) { + r := New(mockClient, nil, &test.kafkaCluster, mockKafkaClientProvider) + + // Mock client + mockClient.EXPECT().List( + context.TODO(), + gomock.AssignableToTypeOf(&corev1.PodList{}), + client.InNamespace("kafka"), + gomock.Any(), + ).Do(func(ctx context.Context, list *corev1.PodList, opts ...client.ListOption) { + list.Items = test.pods + }).Return(nil) + if !test.errorExpected { + mockClient.EXPECT().Delete(context.TODO(), test.currentPod).Return(nil) + } + + // Mock kafka client + mockedKafkaClient := new(mocks.KafkaClient) + mockedKafkaClient.On("AllOfflineReplicas").Return(test.outOfSyncReplicas, nil) + mockedKafkaClient.On("OutOfSyncReplicas").Return(test.outOfSyncReplicas, nil) + mockKafkaClientProvider.On("NewFromCluster", mockClient, &test.kafkaCluster).Return(mockedKafkaClient, func() {}, nil) + + // 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)) + + // Test that the expected error is returned + if test.errorExpected { + assert.NotNil(t, err, "Expected an error but got nil") + } else { + assert.Nil(t, err, "Expected no error but got one") + } + }) + } +} diff --git a/pkg/resources/kafka/mocks/SubResourceClient.go b/pkg/resources/kafka/mocks/SubResourceClient.go new file mode 100644 index 000000000..dfd350001 --- /dev/null +++ b/pkg/resources/kafka/mocks/SubResourceClient.go @@ -0,0 +1,122 @@ +// 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" + "go.uber.org/mock/gomock" + "reflect" + + "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/properties/go.mod b/properties/go.mod index af5d51e26..095da600b 100644 --- a/properties/go.mod +++ b/properties/go.mod @@ -16,3 +16,5 @@ require ( golang.org/x/text v0.9.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 From 16a9fc2f7be12d395e9f9a65aec76c4302245184 Mon Sep 17 00:00:00 2001 From: ctrlaltluc <96051211+ctrlaltluc@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:12:30 +0300 Subject: [PATCH 17/23] Fix flaky test by deleting nodeports explicitly (#67) --- ...luster_controller_externalnodeport_test.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/controllers/tests/kafkacluster_controller_externalnodeport_test.go b/controllers/tests/kafkacluster_controller_externalnodeport_test.go index 9b7372e61..4c62d06d6 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 }) @@ -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 +} From cdfb6b9cd2f6918edede26e9cc0e5ed8bc400aef Mon Sep 17 00:00:00 2001 From: ctrlaltluc <96051211+ctrlaltluc@users.noreply.github.com> Date: Wed, 28 Jun 2023 14:44:10 +0300 Subject: [PATCH 18/23] Allow dashes when parsing broker rack (#68) --- pkg/resources/kafka/kafka.go | 7 +- pkg/resources/kafka/kafka_test.go | 140 ++++++++++++++++++++++++++++-- 2 files changed, 137 insertions(+), 10 deletions(-) diff --git a/pkg/resources/kafka/kafka.go b/pkg/resources/kafka/kafka.go index 97511d6df..d1fe03e4d 100644 --- a/pkg/resources/kafka/kafka.go +++ b/pkg/resources/kafka/kafka.go @@ -96,7 +96,7 @@ const ( var ( // kafkaConfigBrokerRackRegex the regex to parse the "broker.rack" Kafka property used in read-only configs - kafkaConfigBrokerRackRegex = regexp.MustCompile(`broker\.rack\s*=\s*(\w+)`) + kafkaConfigBrokerRackRegex = regexp.MustCompile(`broker\.rack\s*=\s*([\w-]+)`) ) // Reconciler implements the Component Reconciler @@ -221,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") @@ -927,6 +929,9 @@ func (r *Reconciler) handleRollingUpgrade(log logr.Logger, desiredPod, currentPo // 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) > 0 { + log.Info("terminating or pending pods", "terminatingOrPendingPods", terminatingOrPendingPods) + } 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") } diff --git a/pkg/resources/kafka/kafka_test.go b/pkg/resources/kafka/kafka_test.go index 2843ec5fe..c91ee266d 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -1269,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, }, @@ -1293,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, }, @@ -1531,6 +1531,124 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { outOfSyncReplicas: []int32{101}, errorExpected: false, }, + { + testName: "Pod is not deleted if pod is restarting in another AZ, if brokers per AZ < tolerated failures", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{ + {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, + {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, + {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, + }, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + pods: []corev1.Pod{ + {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, + }, + { + testName: "Pod is not deleted if there are out-of-sync replicas in another AZ, if brokers per AZ < tolerated failures", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{ + {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, + {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, + {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, + }, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + pods: []corev1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, + }, + outOfSyncReplicas: []int32{101}, + errorExpected: true, + }, + { + testName: "Pod is not deleted if there are offline replicas in another AZ, if brokers per AZ < tolerated failures", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{ + {Id: 101, ReadOnlyConfig: "broker.rack=az1"}, + {Id: 201, ReadOnlyConfig: "broker.rack=az2"}, + {Id: 301, ReadOnlyConfig: "broker.rack=az3"}, + }, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + pods: []corev1.Pod{ + {ObjectMeta: metav1.ObjectMeta{Name: "kafka-101", Labels: map[string]string{"brokerId": "101"}}}, + {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{101}, + errorExpected: true, + }, + { + testName: "Pod is not deleted if pod is restarting in another AZ, if broker rack value contains dashes", + kafkaCluster: v1beta1.KafkaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kafka", + Namespace: "kafka", + }, + Spec: v1beta1.KafkaClusterSpec{ + Brokers: []v1beta1.Broker{ + {Id: 101, ReadOnlyConfig: "broker.rack=az-1"}, + {Id: 201, ReadOnlyConfig: "broker.rack=az-2"}, + {Id: 301, ReadOnlyConfig: "broker.rack=az-3"}, + }, + RollingUpgradeConfig: v1beta1.RollingUpgradeConfig{ + FailureThreshold: 2, + ConcurrentBrokerRestartsAllowed: 2, + }, + }, + Status: v1beta1.KafkaClusterStatus{State: v1beta1.KafkaClusterRollingUpgrading}, + }, + desiredPod: &corev1.Pod{}, + currentPod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "kafka-201", Labels: map[string]string{"brokerId": "201"}}}, + pods: []corev1.Pod{ + {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, + }, } mockCtrl := gomock.NewController(t) @@ -1556,9 +1674,13 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { } // Mock kafka client - mockedKafkaClient := new(mocks.KafkaClient) - mockedKafkaClient.On("AllOfflineReplicas").Return(test.outOfSyncReplicas, nil) - mockedKafkaClient.On("OutOfSyncReplicas").Return(test.outOfSyncReplicas, nil) + mockedKafkaClient := mocks.NewMockKafkaClient(mockCtrl) + if test.allOfflineReplicas != nil { + mockedKafkaClient.EXPECT().AllOfflineReplicas().Return(test.allOfflineReplicas, nil) + } + if test.outOfSyncReplicas != nil { + mockedKafkaClient.EXPECT().OutOfSyncReplicas().Return(test.outOfSyncReplicas, nil) + } mockKafkaClientProvider.On("NewFromCluster", mockClient, &test.kafkaCluster).Return(mockedKafkaClient, func() {}, nil) // Call the handleRollingUpgrade function with the provided test.desiredPod and test.currentPod From 18e72530fa456d39198f90b9aa2269bdd40031e3 Mon Sep 17 00:00:00 2001 From: Lucian Ilie <96051211+ctrlaltluc@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:52:31 +0300 Subject: [PATCH 19/23] Upgrade Kafka to 3.6.0 (#69) --- docker/kafka/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/kafka/Dockerfile b/docker/kafka/Dockerfile index bee83178b..dd3dde4d4 100644 --- a/docker/kafka/Dockerfile +++ b/docker/kafka/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:latest AS kafka_dist ARG scala_version=2.13 -ARG kafka_version=3.4.1 +ARG kafka_version=3.6.0 ARG kafka_distro_base_url=https://downloads.apache.org/kafka ENV kafka_distro=kafka_$scala_version-$kafka_version.tgz @@ -26,7 +26,7 @@ RUN rm -r kafka_$scala_version-$kafka_version/bin/windows FROM debian:bullseye-slim ARG scala_version=2.13 -ARG kafka_version=3.4.1 +ARG kafka_version=3.6.0 RUN set -eux; \ From edb7ebfa4382684c30e6f4e014eaabbb189edf14 Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Tue, 12 Dec 2023 18:22:19 +0200 Subject: [PATCH 20/23] Upgrade dependencies --- .github/actions/kind-create/action.yaml | 4 +- .github/workflows/ci.yml | 14 +- .github/workflows/e2e-test.yaml | 6 +- .github/workflows/helm.yml | 4 +- .golangci.yml | 16 +- Dockerfile | 2 +- Makefile | 10 +- api/go.mod | 32 +- api/go.sum | 95 ++- api/v1alpha1/zz_generated.deepcopy.go | 1 - api/v1beta1/kafkacluster_types.go | 2 +- api/v1beta1/zz_generated.deepcopy.go | 7 +- charts/kafka-operator/README.md | 2 +- .../crds/cruisecontroloperations.yaml | 3 +- charts/kafka-operator/crds/kafkaclusters.yaml | 731 +++++++++++------ charts/kafka-operator/crds/kafkatopics.yaml | 3 +- charts/kafka-operator/crds/kafkausers.yaml | 3 +- charts/kafka-operator/values.yaml | 2 +- ...anzaicloud.io_cruisecontroloperations.yaml | 3 +- .../kafka.banzaicloud.io_kafkaclusters.yaml | 731 +++++++++++------ .../kafka.banzaicloud.io_kafkatopics.yaml | 3 +- .../crds/kafka.banzaicloud.io_kafkausers.yaml | 3 +- config/base/rbac/role.yaml | 1 - config/base/webhook/manifests.yaml | 1 - .../manager_auth_proxy_patch.yaml | 2 +- .../auth-proxy/manager_auth_proxy_patch.yaml | 2 +- controllers/kafkauser_controller.go | 7 +- .../tests/clusterregistry/suite_test.go | 14 +- controllers/tests/common_test.go | 2 +- .../kafkacluster_controller_envoy_test.go | 4 +- ...luster_controller_externalnodeport_test.go | 8 +- .../tests/kafkatopic_controller_test.go | 2 +- .../tests/kafkauser_controller_test.go | 2 +- controllers/tests/suite_test.go | 14 +- docs/benchmarks/loadgens/Dockerfile | 2 +- go.mod | 161 ++-- go.sum | 752 +++++------------- hack/kafka-test-pod/Dockerfile | 2 +- hack/kafka-test-pod/main.go | 2 +- main.go | 25 +- pkg/kafkaclient/client.go | 2 +- pkg/kafkaclient/dynamicConfig.go | 2 +- pkg/kafkaclient/mock_client.go | 2 +- pkg/kafkaclient/topics.go | 2 +- pkg/kafkaclient/topics_test.go | 2 +- pkg/kafkaclient/users.go | 2 +- pkg/kafkaclient/users_test.go | 2 +- pkg/resources/kafka/configmap.go | 2 +- pkg/resources/kafka/configs.go | 2 +- pkg/resources/kafka/configs_test.go | 2 +- pkg/resources/kafka/kafka_test.go | 32 +- pkg/resources/kafka/mocks/Client.go | 31 + pkg/resources/kafka/mocks/KafkaClient.go | 2 +- .../kafka/mocks/SubResourceClient.go | 3 +- pkg/util/cert/certutil.go | 3 +- pkg/util/util.go | 9 +- pkg/webhooks/errors_test.go | 2 +- pkg/webhooks/kafkacluster_validator.go | 23 +- pkg/webhooks/kafkatopic_validator.go | 18 +- properties/go.mod | 14 +- properties/go.sum | 35 +- tests/e2e/const.go | 1 - tests/e2e/global.go | 4 +- tests/e2e/go.mod | 155 ++-- tests/e2e/go.sum | 413 +++++----- 65 files changed, 1817 insertions(+), 1628 deletions(-) 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/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/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 78658c60a..f2d49110c 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -25,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 }} 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 f9cef8ffc..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 @@ -224,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 6a78be27a..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,16 +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/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/kafkacluster_types.go b/api/v1beta1/kafkacluster_types.go index be017c77d..99f859ccc 100644 --- a/api/v1beta1/kafkacluster_types.go +++ b/api/v1beta1/kafkacluster_types.go @@ -21,7 +21,7 @@ import ( "emperror.dev/errors" - "github.com/imdario/mergo" + "dario.cat/mergo" "github.com/banzaicloud/istio-client-go/pkg/networking/v1beta1" diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 07cb73477..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 @@ -972,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) } @@ -987,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) } 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 5c4296aff..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: @@ -18082,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 @@ -18147,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 @@ -18223,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: @@ -18323,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 @@ -18849,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: @@ -20384,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 @@ -20469,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 @@ -20561,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: @@ -20690,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 @@ -20698,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 @@ -21205,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: 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 5c4296aff..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: @@ -18082,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 @@ -18147,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 @@ -18223,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: @@ -18323,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 @@ -18849,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: @@ -20384,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 @@ -20469,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 @@ -20561,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: @@ -20690,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 @@ -20698,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 @@ -21205,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: 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/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/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 0a92b14d2..663ea3346 100644 --- a/controllers/tests/common_test.go +++ b/controllers/tests/common_test.go @@ -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/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 92f1db6dd..2fc2bb4b6 100644 --- a/controllers/tests/kafkacluster_controller_envoy_test.go +++ b/controllers/tests/kafkacluster_controller_envoy_test.go @@ -736,7 +736,7 @@ func expectEnvoyWithConfigAz1Tls(kafkaCluster *v1beta1.KafkaCluster) { 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.IntVal).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)) @@ -1325,7 +1325,7 @@ func expectEnvoyWithConfigAz2Tls(kafkaCluster *v1beta1.KafkaCluster) { 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.IntVal).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)) diff --git a/controllers/tests/kafkacluster_controller_externalnodeport_test.go b/controllers/tests/kafkacluster_controller_externalnodeport_test.go index 4c62d06d6..be9ad4229 100644 --- a/controllers/tests/kafkacluster_controller_externalnodeport_test.go +++ b/controllers/tests/kafkacluster_controller_externalnodeport_test.go @@ -239,7 +239,7 @@ var _ = Describe("KafkaClusterNodeportExternalAccess", func() { ContainerPort: 9733, Type: "plaintext", }, - ExternalStartingPort: 30300, + ExternalStartingPort: 30410, IngressServiceSettings: v1beta1.IngressServiceSettings{ HostnameOverride: ".external.nodeport.com", }, @@ -280,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), }, }, }, 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/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/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 401d1f2fd..be99ba78c 100644 --- a/go.mod +++ b/go.mod @@ -1,148 +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.7 - github.com/onsi/gomega v1.27.8 - 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.9.1 // 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.5.0 // 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 + 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.0-adbe + 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 ) -// 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 +// exclude github.com/imdario/mergo v0.3.6 diff --git a/go.sum b/go.sum index 7dbd0a3c1..726c25bc9 100644 --- a/go.sum +++ b/go.sum @@ -1,251 +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/adobe/go-cruise-control v0.6.0-adbe h1:Qr9NJ4clpbgNmZQK52b96fg+7+wnrjNRF7i7upHLUk0= -github.com/adobe/go-cruise-control v0.6.0-adbe/go.mod h1:52C8XiTZjSmFVD+y76rd2al//GTJk9mSwkcHs2LGSvA= -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/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/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= @@ -254,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= @@ -276,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= @@ -347,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.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +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.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= -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= @@ -437,243 +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.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +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.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +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.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.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.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= -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.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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -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/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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.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= @@ -681,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.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +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= @@ -833,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/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/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/kafka/configmap.go b/pkg/resources/kafka/configmap.go index 3c900e7cd..5c4645c4a 100644 --- a/pkg/resources/kafka/configmap.go +++ b/pkg/resources/kafka/configmap.go @@ -163,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)}, 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_test.go b/pkg/resources/kafka/kafka_test.go index c91ee266d..e6c891f15 100644 --- a/pkg/resources/kafka/kafka_test.go +++ b/pkg/resources/kafka/kafka_test.go @@ -16,7 +16,6 @@ package kafka import ( "context" - "go.uber.org/mock/gomock" "reflect" "testing" "time" @@ -25,6 +24,7 @@ import ( "github.com/go-logr/logr" "github.com/onsi/gomega" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -1176,7 +1176,7 @@ func TestReconcileKafkaPvcDiskRemoval(t *testing.T) { // Mock the status update call mockClient.EXPECT().Status().Return(mockSubResourceClient).AnyTimes() - mockSubResourceClient.EXPECT().Update(context.TODO(), gomock.AssignableToTypeOf(&v1beta1.KafkaCluster{})).Do(func(ctx context.Context, kafkaCluster *v1beta1.KafkaCluster, opts ...client.SubResourceUpdateOption) { + 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() @@ -1390,8 +1390,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"}}}, }, - outOfSyncReplicas: []int32{101}, - errorExpected: true, + outOfSyncReplicas: []int32{101}, + allOfflineReplicas: []int32{}, + errorExpected: true, }, { testName: "Pod is deleted if allowed concurrent restarts is not specified and failure threshold is not reached", @@ -1424,7 +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, + errorExpected: false, + allOfflineReplicas: []int32{}, + outOfSyncReplicas: []int32{}, }, { testName: "Pod is not deleted if pod is restarting in another AZ, even if allowed concurrent restarts is not reached", @@ -1458,8 +1461,7 @@ 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"}}}, }, - outOfSyncReplicas: []int32{201}, - errorExpected: true, + errorExpected: true, }, { testName: "Pod is not deleted if failure is in another AZ, even if allowed concurrent restarts is not reached", @@ -1493,8 +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"}}}, }, - outOfSyncReplicas: []int32{201}, - errorExpected: true, + outOfSyncReplicas: []int32{201}, + allOfflineReplicas: []int32{}, + errorExpected: true, }, { testName: "Pod is deleted if failure is in same AZ and allowed concurrent restarts is not reached", @@ -1528,8 +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"}}}, }, - outOfSyncReplicas: []int32{101}, - errorExpected: false, + outOfSyncReplicas: []int32{101}, + allOfflineReplicas: []int32{}, + errorExpected: false, }, { testName: "Pod is not deleted if pod is restarting in another AZ, if brokers per AZ < tolerated failures", @@ -1587,8 +1591,9 @@ 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"}}}, }, - outOfSyncReplicas: []int32{101}, - errorExpected: true, + outOfSyncReplicas: []int32{101}, + allOfflineReplicas: []int32{}, + errorExpected: true, }, { testName: "Pod is not deleted if there are offline replicas in another AZ, if brokers per AZ < tolerated failures", @@ -1618,6 +1623,7 @@ func TestReconcileConcurrentBrokerRestartsAllowed(t *testing.T) { {ObjectMeta: metav1.ObjectMeta{Name: "kafka-301", Labels: map[string]string{"brokerId": "301"}}}, }, allOfflineReplicas: []int32{101}, + outOfSyncReplicas: []int32{}, errorExpected: true, }, { 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 index dfd350001..5df166e24 100644 --- a/pkg/resources/kafka/mocks/SubResourceClient.go +++ b/pkg/resources/kafka/mocks/SubResourceClient.go @@ -16,9 +16,10 @@ package mocks import ( "context" - "go.uber.org/mock/gomock" "reflect" + "go.uber.org/mock/gomock" + "sigs.k8s.io/controller-runtime/pkg/client" ) 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/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/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 d2d8a6b41..952abd140 100644 --- a/pkg/webhooks/kafkacluster_validator.go +++ b/pkg/webhooks/kafkacluster_validator.go @@ -19,6 +19,9 @@ import ( "fmt" 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" @@ -33,7 +36,7 @@ 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 kafkaClusterNew := newObj.(*banzaicloudv1beta1.KafkaCluster) log := s.Log.WithValues("name", kafkaClusterNew.GetName(), "namespace", kafkaClusterNew.GetNamespace()) @@ -44,16 +47,16 @@ func (s KafkaClusterValidator) ValidateUpdate(ctx context.Context, oldObj, newOb } 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()) @@ -64,17 +67,17 @@ 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 +func (s KafkaClusterValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + return nil, nil } // checkListeners validates the spec.listenersConfig object @@ -163,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) @@ -185,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/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 095da600b..983c85724 100644 --- a/properties/go.mod +++ b/properties/go.mod @@ -1,20 +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= From 5f78c06c89b101304f454ca65d0f3a56f3a173cf Mon Sep 17 00:00:00 2001 From: Razvan Dobre Date: Tue, 19 Dec 2023 17:20:30 +0200 Subject: [PATCH 21/23] Fix wrong port on expectEnvoyWithConfigAz2Tls test (#70) --- controllers/tests/kafkacluster_controller_envoy_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/tests/kafkacluster_controller_envoy_test.go b/controllers/tests/kafkacluster_controller_envoy_test.go index 2fc2bb4b6..60176badb 100644 --- a/controllers/tests/kafkacluster_controller_envoy_test.go +++ b/controllers/tests/kafkacluster_controller_envoy_test.go @@ -1359,7 +1359,7 @@ func expectEnvoyWithConfigAz2Tls(kafkaCluster *v1beta1.KafkaCluster) { }, corev1.ContainerPort{ Name: "tcp-health", - ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyAdminPort(), + ContainerPort: kafkaCluster.Spec.EnvoyConfig.GetEnvoyHealthCheckPort(), Protocol: corev1.ProtocolTCP, }, )) From 73839214722f27b73781c9f34050ab4e4cc69148 Mon Sep 17 00:00:00 2001 From: Cristian-Petrut Petrache Date: Fri, 22 Dec 2023 14:44:47 +0200 Subject: [PATCH 22/23] Upgrade Kafka to 3.6.1 (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Petruț™ --- docker/kafka/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/kafka/Dockerfile b/docker/kafka/Dockerfile index dd3dde4d4..f48bf0ed8 100644 --- a/docker/kafka/Dockerfile +++ b/docker/kafka/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:latest AS kafka_dist ARG scala_version=2.13 -ARG kafka_version=3.6.0 +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 @@ -26,7 +26,7 @@ RUN rm -r kafka_$scala_version-$kafka_version/bin/windows FROM debian:bullseye-slim ARG scala_version=2.13 -ARG kafka_version=3.6.0 +ARG kafka_version=3.6.1 RUN set -eux; \ From 249e02a0efcad153f5fa10d8c5d5b40adfde66cc Mon Sep 17 00:00:00 2001 From: Adi Muraru Date: Fri, 22 Dec 2023 18:20:59 +0200 Subject: [PATCH 23/23] Upgrade Kafka image to use Java v21 --- docker/kafka/Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docker/kafka/Dockerfile b/docker/kafka/Dockerfile index f48bf0ed8..07b0b797f 100644 --- a/docker/kafka/Dockerfile +++ b/docker/kafka/Dockerfile @@ -36,22 +36,24 @@ RUN set -eux; \ ; \ rm -rf /var/lib/apt/lists/* -ENV JAVA_HOME /usr/local/openjdk-17 +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/17/latest/jdk-17_linux-x64_bin.tar.gz'; \ - downloadSha256='https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz.sha256'; \ + 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/17/latest/jdk-17_linux-aarch64_bin.tar.gz'; \ - downloadSha256='https://download.oracle.com/java/17/latest/jdk-17_linux-aarch64_bin.tar.gz.sha256'; \ + 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; \