diff --git a/.github/workflows/zitadel.yml b/.github/workflows/zitadel.yml index ba9b1ddb31..b0ff73e4ef 100644 --- a/.github/workflows/zitadel.yml +++ b/.github/workflows/zitadel.yml @@ -12,8 +12,6 @@ on: env: REGISTRY: ghcr.io - OPERATOR_IMAGE_NAME: ${{ github.repository }}-operator - CRDB_IMAGE_NAME: ${{ github.repository }}-crbackup ARTIFACTS_FOLDER: './artifacts' jobs: @@ -158,140 +156,10 @@ jobs: push: true cache-from: type=gha,scope=${{ github.workflow }} cache-to: type=gha,scope=${{ github.workflow }},mode=max - - zitadel-operator: - name: Build ZITADEL Operator ${{ matrix.goos }}-${{ matrix.goarch }} - needs: refs - runs-on: ubuntu-18.04 - strategy: - matrix: - goos: [ 'linux', 'darwin', 'windows' ] - goarch: [ 'amd64' ] - steps: - - name: Source checkout - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - uses: docker/build-push-action@v2 - with: - context: . - file: ./build/operator/Dockerfile - platforms: linux/amd64 - cache-from: type=gha,scope=${{ matrix.goos }}-${{ matrix.goarch }} - cache-to: type=gha,scope=${{ matrix.goos }}-${{ matrix.goarch }},mode=max - outputs: type=local,dest=/tmp/operator - build-args: | - OS=${{ matrix.goos }} - ARCH=${{ matrix.goarch }} - VERSION=${{ needs.refs.outputs.version }} - GITHUBOAUTHCLIENTID=${{ secrets.GITHUBOAUTHCLIENTID }} - GITHUBOAUTHCLIENTSECRET=${{ secrets.GITHUBOAUTHCLIENTSECRET }} - - shell: bash - run: | - mv /tmp/operator/zitadelctl /tmp/operator/zitadelctl-${{ matrix.goos }}-${{ matrix.goarch }} - - uses: actions/upload-artifact@v2 - with: - name: zitadelctl-${{ matrix.goos }}-${{ matrix.goarch }} - path: /tmp/operator/zitadelctl-${{ matrix.goos }}-${{ matrix.goarch }} - - zitadel-operator-codecov: - name: Upload ZITADEL Operator Codecov ${{ matrix.goos }}-${{ matrix.goarch }} - needs: [refs, zitadel-operator] - runs-on: ubuntu-18.04 - strategy: - matrix: - goos: [ 'linux' ] - goarch: [ 'amd64' ] - steps: - - name: Source checkout - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - uses: docker/build-push-action@v2 - with: - context: . - file: ./build/operator/Dockerfile - platforms: linux/amd64 - cache-from: type=gha,scope=${{ matrix.goos }}-${{ matrix.goarch }} - target: go-codecov - outputs: type=local,dest=/tmp/operator - - uses: codecov/codecov-action@v1 - with: - files: /tmp/operator/profile.cov - name: codecov-go - - zitadel-operator-image: - name: Package ZITADEL Operator Image ${{ matrix.goos }}-${{ matrix.goarch }} - needs: [refs, zitadel-operator] - runs-on: ubuntu-18.04 - if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }} - strategy: - matrix: - goos: [ 'linux' ] - goarch: [ 'amd64' ] - steps: - - name: Source checkout - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - registry: ${{ env.REGISTRY }} - - uses: docker/build-push-action@v2 - with: - context: . - file: ./build/operator/Dockerfile - platforms: linux/amd64 - tags: ${{ env.REGISTRY }}/${{ env.OPERATOR_IMAGE_NAME }}:${{ needs.refs.outputs.sha_short }},${{ env.REGISTRY }}/${{ env.OPERATOR_IMAGE_NAME }}:${{ needs.refs.outputs.short_ref }} - push: true - cache-from: type=gha,scope=${{ matrix.goos }}-${{ matrix.goarch }} - build-args: | - OS=${{ matrix.goos }} - ARCH=${{ matrix.goarch }} - VERSION=${{ needs.refs.outputs.version }} - - crdb-image: - name: Package ZITADEL CockroachDB Image - needs: refs - runs-on: ubuntu-18.04 - if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }} - steps: - - name: Source checkout - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - registry: ${{ env.REGISTRY }} - - uses: docker/build-push-action@v2 - name: buildandpush - with: - context: . - file: ./build/cr-backup/Dockerfile - platforms: linux/amd64 - tags: ${{ env.REGISTRY }}/${{ env.CRDB_IMAGE_NAME }}:${{ needs.refs.outputs.sha_short }},${{ env.REGISTRY }}/${{ env.CRDB_IMAGE_NAME }}:${{ needs.refs.outputs.short_ref }} - push: true - cache-from: type=gha,scope=${{ github.workflow }} - cache-to: type=gha,scope=${{ github.workflow }} - release: name: Semantic Release Images and Artifacts runs-on: ubuntu-18.04 - needs: [ refs, zitadel-image, zitadel-operator-image, crdb-image ] + needs: [ refs, zitadel-image ] if: ${{ github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main' }} env: DOCKER_USERNAME: ${{ github.repository_owner }} @@ -307,10 +175,6 @@ jobs: registry: ${{ env.REGISTRY }} - name: Docker Pull ZITADEL Image run: docker pull $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.sha_short }} - - name: Docker Pull ZITADEL Operator Image - run: docker pull $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} - - name: Docker Pull CockroachDB Image - run: docker pull $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} - name: Download zitadelctl Artifacts uses: actions/download-artifact@v2 with: @@ -338,39 +202,27 @@ jobs: - name: Docker Tag Version run: | docker tag $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.sha_short }} $REGISTRY/$GITHUB_REPOSITORY:${{ steps.semantic.outputs.new_release_version }} - docker tag $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$OPERATOR_IMAGE_NAME:${{ steps.semantic.outputs.new_release_version }} - docker tag $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$CRDB_IMAGE_NAME:${{ steps.semantic.outputs.new_release_version }} if: steps.semantic.outputs.new_release_published == 'true' - name: Docker Tag Latest run: | docker tag $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.sha_short }} $REGISTRY/$GITHUB_REPOSITORY:latest - docker tag $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$OPERATOR_IMAGE_NAME:latest - docker tag $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$CRDB_IMAGE_NAME:latest if: steps.semantic.outputs.new_release_published == 'true' - name: Docker Push Version run: | docker push $REGISTRY/$GITHUB_REPOSITORY:${{ steps.semantic.outputs.new_release_version }} - docker push $REGISTRY/$OPERATOR_IMAGE_NAME:${{ steps.semantic.outputs.new_release_version }} - docker push $REGISTRY/$CRDB_IMAGE_NAME:${{ steps.semantic.outputs.new_release_version }} if: steps.semantic.outputs.new_release_published == 'true' - name: Docker Push Latest run: | docker push $REGISTRY/$GITHUB_REPOSITORY:latest - docker push $REGISTRY/$OPERATOR_IMAGE_NAME:latest - docker push $REGISTRY/$CRDB_IMAGE_NAME:latest if: steps.semantic.outputs.new_release_published == 'true' - name: Docker Tag Version run: | docker tag $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.sha_short }} $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.short_ref }} - docker tag $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.short_ref }} - docker tag $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.sha_short }} $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.short_ref }} if: steps.semantic.outputs.new_release_published != 'true' && needs.refs.outputs.short_ref != 'main' && needs.refs.outputs.short_ref != '' - name: Docker Push Version run: | docker push $REGISTRY/$GITHUB_REPOSITORY:${{ needs.refs.outputs.short_ref }} - docker push $REGISTRY/$OPERATOR_IMAGE_NAME:${{ needs.refs.outputs.short_ref }} - docker push $REGISTRY/$CRDB_IMAGE_NAME:${{ needs.refs.outputs.short_ref }} if: steps.semantic.outputs.new_release_published != 'true' && needs.refs.outputs.short_ref != 'main' && needs.refs.outputs.short_ref != '' - name: Development Release id: create_release @@ -398,4 +250,4 @@ jobs: SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} with: version: zitadel-${{ needs.refs.outputs.version }} - projects: "console database-operator zitadel zitadel-operator zitadelctl" + projects: "console zitadel zitadelctl" diff --git a/build/cr-backup/Dockerfile b/build/cr-backup/Dockerfile deleted file mode 100644 index 6ff695f1ab..0000000000 --- a/build/cr-backup/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM cockroachdb/cockroach:v20.2.3 - -RUN microdnf install curl wget tar gzip - -RUN wget https://storage.googleapis.com/oauth2l/latest/linux_amd64.tgz -RUN tar zxvf linux_amd64.tgz -RUN mv linux_amd64/oauth2l /usr/local/bin/oauth2l && rm -rf linux_amd64 - -COPY build/cr-backup/scripts/backup-cockroach.sh /scripts/backup.sh -RUN chmod +x /scripts/backup.sh - -COPY build/cr-backup/scripts/restore-cockroach.sh /scripts/restore.sh -RUN chmod +x /scripts/restore.sh - -COPY build/cr-backup/scripts/clean-db-cockroach.sh /scripts/clean-db.sh -RUN chmod +x /scripts/clean-db.sh -COPY build/cr-backup/scripts/clean-migration-cockroach.sh /scripts/clean-migration.sh -RUN chmod +x /scripts/clean-migration.sh -COPY build/cr-backup/scripts/clean-user-cockroach.sh /scripts/clean-user.sh -RUN chmod +x /scripts/clean-user.sh - -ENTRYPOINT [ "/cockroach" ] diff --git a/build/cr-backup/scripts/backup-cockroach.sh b/build/cr-backup/scripts/backup-cockroach.sh deleted file mode 100644 index 7f15c7ba1d..0000000000 --- a/build/cr-backup/scripts/backup-cockroach.sh +++ /dev/null @@ -1,17 +0,0 @@ -env=$1 -bucket=$2 -db=$3 -folder=$4 -safile=$5 -certs=$6 -name=$7 - -filenamelocal=zitadel-${db}.sql -filenamebucket=zitadel-${db}-${name}.sql - -/cockroach/cockroach.sh dump --dump-mode=data --certs-dir=${certs} --host=cockroachdb-public:26257 ${db} > ${folder}/${filenamelocal} -curl -X POST \ - -H "$(oauth2l header --json ${safile} cloud-platform)" \ - -H "Content-Type: application/json" \ - --data-binary @${folder}/${filenamelocal} \ - "https://storage.googleapis.com/upload/storage/v1/b/${bucket}/o?uploadType=media&name=${env}/${name}/${filenamebucket}" \ No newline at end of file diff --git a/build/cr-backup/scripts/clean-db-cockroach.sh b/build/cr-backup/scripts/clean-db-cockroach.sh deleted file mode 100644 index c263004db9..0000000000 --- a/build/cr-backup/scripts/clean-db-cockroach.sh +++ /dev/null @@ -1,4 +0,0 @@ -certs=$1 -db=$2 - -/cockroach/cockroach.sh sql --certs-dir=${certs} --host=cockroachdb-public:26257 -e "DROP DATABASE IF EXISTS ${db} CASCADE;" diff --git a/build/cr-backup/scripts/clean-migration-cockroach.sh b/build/cr-backup/scripts/clean-migration-cockroach.sh deleted file mode 100644 index 0bce3645b4..0000000000 --- a/build/cr-backup/scripts/clean-migration-cockroach.sh +++ /dev/null @@ -1,3 +0,0 @@ -certs=$1 - -/cockroach/cockroach.sh sql --certs-dir=${certs} --host=cockroachdb-public:26257 -e "TRUNCATE defaultdb.flyway_schema_history;" \ No newline at end of file diff --git a/build/cr-backup/scripts/clean-user-cockroach.sh b/build/cr-backup/scripts/clean-user-cockroach.sh deleted file mode 100644 index de00b8fc2f..0000000000 --- a/build/cr-backup/scripts/clean-user-cockroach.sh +++ /dev/null @@ -1,4 +0,0 @@ -certs=$1 -db=$2 - -/cockroach/cockroach.sh sql --certs-dir=${certs} --host=cockroachdb-public:26257 -e "DROP USER IF EXISTS ${db};" \ No newline at end of file diff --git a/build/cr-backup/scripts/restore-cockroach.sh b/build/cr-backup/scripts/restore-cockroach.sh deleted file mode 100644 index e5d1ec8818..0000000000 --- a/build/cr-backup/scripts/restore-cockroach.sh +++ /dev/null @@ -1,33 +0,0 @@ -bucket=$1 -env=$2 -name=$3 -db=$4 -safile=$5 -certs=$6 - -urlencode() { - # urlencode - old_lc_collate=$LC_COLLATE - LC_COLLATE=C - - local length="${#1}" - for (( i = 0; i < length; i++ )); do - local c="${1:i:1}" - case $c in - [a-zA-Z0-9.~_-]) printf "$c" ;; - *) printf '%%%02X' "'$c" ;; - esac - done - - LC_COLLATE=$old_lc_collate -} - -filenamelocal=zitadel-${db}.sql -filenamebucket=zitadel-${db}-${name}.sql - -curl -X GET \ - -H "$(oauth2l header --json ${safile} cloud-platform)" \ - -o "${filenamelocal}" \ - "https://storage.googleapis.com/storage/v1/b/${bucket}/o/$(urlencode ${env}/${name}/${filenamebucket})?alt=media" - -/cockroach/cockroach.sh sql --certs-dir=${certs} --host=cockroachdb-public:26257 --database=${db} < ${filenamelocal} diff --git a/build/operator/.dockerignore b/build/operator/.dockerignore deleted file mode 100644 index cf9284709f..0000000000 --- a/build/operator/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -**/statik/statik.go \ No newline at end of file diff --git a/build/operator/Dockerfile b/build/operator/Dockerfile deleted file mode 100644 index fb844b244f..0000000000 --- a/build/operator/Dockerfile +++ /dev/null @@ -1,65 +0,0 @@ -####################### -## By default we build the prod enviroment -ARG ENV=prod - -####################### -## Go base build -## Speed up this step by mounting your local go mod pkg directory -####################### -FROM golang:1.16 as go-base - -WORKDIR src/github.com/caos/zitadel/ -COPY go.mod go.sum ./ -RUN go mod download - - -## Go test -FROM go-base as go-test -COPY . . -#Migrations for cockroach-secure -RUN go install github.com/rakyll/statik -RUN ./build/operator/prebuild.sh ./migrations - -RUN go test -race -v -coverprofile=profile.cov ./operator/... - -## Go test -FROM scratch as go-codecov -COPY --from=go-test /go/src/github.com/caos/zitadel/profile.cov profile.cov - -## Go prod build -FROM go-test as prod-go-build - - -ARG ARCH=amd64 -ARG OS=linux -ARG VERSION=none -ARG GITHUBOAUTHCLIENTID=none -ARG GITHUBOAUTHCLIENTSECRET=none -RUN GOOS=${OS} GOARCH=${ARCH} ./build/operator/build.sh ${VERSION} - -## Go dev build -FROM go-base as dev-go-build -RUN go get github.com/go-delve/delve/cmd/dlv - -####################### -## Final Production Image -####################### -FROM alpine:latest as artifact -RUN adduser -D zitadel - -ARG ARCH=amd64 -ARG OS=linux - -RUN apk add -U --no-cache ca-certificates - -COPY --from=prod-go-build /go/src/github.com/caos/zitadel/zitadelctl /app/zitadelctl -RUN chmod a+x /app/zitadelctl - -## Scratch Image -FROM scratch as final -COPY --from=artifact /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -COPY --from=artifact /etc/passwd /etc/passwd -COPY --from=artifact /app / -USER zitadel -HEALTHCHECK NONE -ENTRYPOINT ["/zitadelctl"] diff --git a/build/operator/build.sh b/build/operator/build.sh deleted file mode 100755 index 67e1cb4637..0000000000 --- a/build/operator/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -set -e - -CGO_ENABLED=0 go build \ - -a \ - -installsuffix cgo \ - -ldflags "$(./build/operator/ldflags.sh "${1}")" \ - -o zitadelctl \ - ./cmd/zitadelctl/main.go diff --git a/build/operator/ldflags.sh b/build/operator/ldflags.sh deleted file mode 100755 index bb21c107f6..0000000000 --- a/build/operator/ldflags.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -set -e - -VERSION=${1} -if [ "${VERSION}" == "" ]; then - VERSION="$(git rev-parse --abbrev-ref HEAD | sed -e 's/heads\///')" -fi - -echo -n "-extldflags -static -X main.Version=${VERSION} -X main.githubClientID=${GITHUBOAUTHCLIENTID} -X main.githubClientSecret=${GITHUBOAUTHCLIENTSECRET}" diff --git a/build/operator/prebuild.sh b/build/operator/prebuild.sh deleted file mode 100755 index b9cb991522..0000000000 --- a/build/operator/prebuild.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e - -statik -src=$1 \ No newline at end of file diff --git a/build/zitadel/Dockerfile b/build/zitadel/Dockerfile index ae436ff070..44feb82502 100644 --- a/build/zitadel/Dockerfile +++ b/build/zitadel/Dockerfile @@ -148,13 +148,13 @@ FROM go-test as prod-go-build ARG BUILDARCH ARG VERSION="" -RUN CGO_ENABLED=0 GOOS=linux GOARCH=${BUILDARCH} go build -a -installsuffix cgo -ldflags "-X main.version=${VERSION:-'dev'} -extldflags \"-static\"" -o zitadel-linux-${BUILDARCH} cmd/zitadel/main.go +RUN CGO_ENABLED=0 GOOS=linux GOARCH=${BUILDARCH} go build -a -installsuffix cgo -ldflags "-X main.version=${VERSION:-'dev'} -extldflags \"-static\"" -o zitadel-linux-${BUILDARCH} main.go ####################### ## Go dev build ####################### FROM go-base as dev-go-build -ENTRYPOINT [ "go", "run", "cmd/zitadel/main.go" ] +ENTRYPOINT [ "go", "run", "main.go" ] ####################### ## Only Copy Assets diff --git a/go.mod b/go.mod index 53f86d1fe0..fe96d2fb7b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/caos/zitadel go 1.17 require ( - cloud.google.com/go/storage v1.18.2 github.com/BurntSushi/toml v0.4.1 github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0 @@ -12,14 +11,9 @@ require ( github.com/VictoriaMetrics/fastcache v1.8.0 github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b github.com/allegro/bigcache v1.2.1 - github.com/aws/aws-sdk-go-v2 v1.11.2 - github.com/aws/aws-sdk-go-v2/config v1.11.0 - github.com/aws/aws-sdk-go-v2/credentials v1.6.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0 github.com/boombuler/barcode v1.0.1 - github.com/caos/logging v0.2.1 + github.com/caos/logging v0.3.0 github.com/caos/oidc v1.0.1 - github.com/caos/orbos v1.5.14-0.20211102124704-34db02bceed2 github.com/cockroachdb/cockroach-go/v2 v2.2.4 github.com/dop251/goja v0.0.0-20211129110639-4739a1d10a51 github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d @@ -48,6 +42,7 @@ require ( github.com/pquerna/otp v1.3.0 github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.8.0 + github.com/sirupsen/logrus v1.8.1 github.com/sony/sonyflake v1.0.0 github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 @@ -69,41 +64,20 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/text v0.3.7 golang.org/x/tools v0.1.8 - google.golang.org/api v0.63.0 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.6.0 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - gotest.tools v2.2.0+incompatible - k8s.io/api v0.22.4 - k8s.io/apiextensions-apiserver v0.22.2 - k8s.io/apimachinery v0.22.4 - k8s.io/client-go v0.22.4 - sigs.k8s.io/controller-runtime v0.10.3 sigs.k8s.io/yaml v1.3.0 ) require ( cloud.google.com/go v0.99.0 // indirect cloud.google.com/go/trace v1.0.0 // indirect - github.com/AlecAivazis/survey/v2 v2.3.2 // indirect - github.com/AppsFlyer/go-sundheit v0.2.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 // indirect - github.com/aws/smithy-go v1.9.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 // indirect @@ -112,69 +86,49 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/emirpasic/gods v1.12.0 // indirect github.com/envoyproxy/go-control-plane v0.10.1 // indirect - github.com/evanphx/json-patch v4.11.0+incompatible // indirect github.com/felixge/httpsnoop v1.0.2 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fxamacker/cbor/v2 v2.2.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.0.0 // indirect - github.com/go-git/go-git/v5 v5.2.0 // indirect - github.com/go-logr/logr v0.4.0 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/gobuffalo/flect v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.1.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.0.21 // indirect github.com/google/go-cmp v0.5.6 // indirect - github.com/google/go-github/v31 v31.0.0 // indirect - github.com/google/go-querystring v1.0.0 // indirect - github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/gax-go/v2 v2.1.1 // indirect - github.com/googleapis/gnostic v0.5.5 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 // indirect github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c // indirect - github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect - github.com/klauspost/compress v1.13.5 // indirect + github.com/klauspost/compress v1.14.2 // indirect github.com/klauspost/cpuid v1.3.1 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/magiconair/properties v1.8.5 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/minio/md5-simd v1.1.0 // indirect github.com/minio/sha256-simd v0.1.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 // indirect github.com/muesli/kmeans v0.2.1 // indirect github.com/pelletier/go-toml v1.9.4 // indirect - github.com/pires/go-proxyproto v0.6.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect @@ -182,8 +136,6 @@ require ( github.com/prometheus/procfs v0.6.0 // indirect github.com/rs/xid v1.2.1 // indirect github.com/satori/go.uuid v1.2.0 // indirect - github.com/sergi/go-diff v1.1.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/afero v1.8.1 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -192,7 +144,6 @@ require ( github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect github.com/wcharczuk/go-chart/v2 v2.1.0 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/ssh-agent v0.2.1 // indirect github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b // indirect go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 // indirect @@ -200,23 +151,14 @@ require ( go.opentelemetry.io/proto/otlp v0.10.0 // indirect golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 // indirect golang.org/x/mod v0.5.1 // indirect - golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect + golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba // indirect golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect - golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + google.golang.org/api v0.63.0 // indirect google.golang.org/appengine v1.6.7 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.4 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.22.2 // indirect - k8s.io/klog/v2 v2.9.0 // indirect - k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c // indirect - k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect - sigs.k8s.io/controller-tools v0.7.0 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.4 diff --git a/go.sum b/go.sum index 81b3aa644b..7eed40d7d1 100644 --- a/go.sum +++ b/go.sum @@ -39,7 +39,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -51,25 +50,10 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl 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= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY= -cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM= cloud.google.com/go/trace v1.0.0 h1:laKx2y7IWMjguCe5zZx6n7qLtREk4kyE69SXVC0VSN8= cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= -github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/AppsFlyer/go-sundheit v0.2.0 h1:FArqX+HbqZ6U32RC3giEAWRUpkggqxHj91KIvxNgwjU= -github.com/AppsFlyer/go-sundheit v0.2.0/go.mod h1:rCRkVTMQo7/krF7xQ9X0XEF1an68viFR6/Gy02q+4ds= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -83,7 +67,6 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0 h1:38fNtfhHY6bs22b/D6+hDzO6JR0rDzpGPD36dY2uPL4= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.0.0/go.mod h1:jE23wM1jvwSKgdGcoOkj5j9n1VWtncW36pL2bK1JU+0= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= 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 v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -92,25 +75,16 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= -github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.8.0 h1:ybZqS7kRy8YVzYsI09GLzQhs7iqS6cOEH2avtknD1SU= github.com/VictoriaMetrics/fastcache v1.8.0/go.mod h1:n7Sl+ioh/HlWeYHLSIBIE8TcZFHg/+xgvomWSS5xuEE= -github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c/go.mod h1:p/7Wos+jcfrnwLqqzJMZ0s323kfVtJPW+HUvAANklVQ= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -120,8 +94,6 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 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/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -129,43 +101,7 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go-v2 v1.11.2 h1:SDiCYqxdIYi6HgQfAWRhgdZrdnOuGyLDJVRSWLeHWvs= -github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= -github.com/aws/aws-sdk-go-v2/config v1.11.0 h1:Czlld5zBB61A3/aoegA9/buZulwL9mHHfizh/Oq+Kqs= -github.com/aws/aws-sdk-go-v2/config v1.11.0/go.mod h1:VrQDJGFBM5yZe+IOeenNZ/DWoErdny+k2MHEIpwDsEY= -github.com/aws/aws-sdk-go-v2/credentials v1.6.4 h1:2hvbUoHufns0lDIsaK8FVCMukT1WngtZPavN+W2FkSw= -github.com/aws/aws-sdk-go-v2/credentials v1.6.4/go.mod h1:tTrhvBPHyPde4pdIPSba4Nv7RYr4wP9jxXEDa1bKn/8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 h1:KiN5TPOLrEjbGCvdTQR4t0U4T87vVwALZ5Bg3jpMqPY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2/go.mod h1:dF2F6tXEOgmW5X1ZFO/EPtWrcm7XkW07KNcJUGNtt4s= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 h1:XJLnluKuUxQG255zPNe+04izXl7GSyUVafIsgfv9aw4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 h1:EauRoYZVNPlidZSZJDscjJBQ22JhVF2+tdteatax2Ak= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 h1:IQup8Q6lorXeiA/rK72PeToWoWK8h7VAPgHNWdSrtgE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2/go.mod h1:VITe/MdW6EMXPb0o0txu/fsonXbMHUU2OC2Qp7ivU4o= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 h1:lPLbw4Gn59uoKqvOfSnkJr54XWk5Ak1NK20ZEiSWb3U= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 h1:CKdUNKmuilw/KNmO2Q53Av8u+ZyXMC2M9aX8Z+c/gzg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2/go.mod h1:FgR1tCsn8C6+Hf+N5qkfrE4IXvUL1RgW87sunJ+5J4I= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2 h1:GnPGH1FGc4fkn0Jbm/8r2+nPOwSJjYPyHSqFSvY1ii8= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2/go.mod h1:eDUYjOYt4Uio7xfHi5jOsO393ZG8TSfZB92a3ZNadWM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0 h1:vUM2P60BI755i35Gyik4s/lXKcnpEbnvw2Vud+soqpI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0/go.mod h1:lQ5AeEW2XWzu8hwQ3dCqZFWORQ3RntO0Kq135Xd9VCo= -github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 h1:2IDmvSb86KT44lSg1uU4ONpzgWLOuApRl6Tg54mZ6Dk= -github.com/aws/aws-sdk-go-v2/service/sso v1.6.2/go.mod h1:KnIpszaIdwI33tmc/W/GGXyn22c1USYxA/2KyvoeDY0= -github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 h1:QKR7wy5e650q70PFKMfGF9sTo0rZgUevSSJ4wxmyWXk= -github.com/aws/aws-sdk-go-v2/service/sts v1.11.1/go.mod h1:UV2N5HaPfdbDpkgkz4sRzWCvQswZjdO1FfqCWl0t7RA= -github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58= -github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.2.0 h1:9Re3G2TWxkE06LdMWMpcY6KV81GLXMGiYpPYUPkFAws= github.com/benbjohnson/clock v1.2.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -173,35 +109,25 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce 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/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 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/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= -github.com/caos/logging v0.2.1 h1:412Z2ytE+YDwVg6JhwgpHo2TjDhb8kbLOFEWrJ7t3i4= -github.com/caos/logging v0.2.1/go.mod h1:B8QNS0WDmR2Keac52Fw+XN4ZJkzLDGrcRIPB2Ux4uRo= -github.com/caos/oidc v1.0.0/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU= +github.com/caos/logging v0.3.0 h1:PMKd47Aqr98FjAPcAE8v3SCe8eqTEclytruND/zc7QU= +github.com/caos/logging v0.3.0/go.mod h1:B8QNS0WDmR2Keac52Fw+XN4ZJkzLDGrcRIPB2Ux4uRo= github.com/caos/oidc v1.0.1 h1:8UHAPynCObwaqortppDtJFktjqLDLYSLidkNy0Num4o= github.com/caos/oidc v1.0.1/go.mod h1:4l0PPwdc6BbrdCFhNrRTUddsG292uHGa7gE2DSEIqoU= -github.com/caos/orbos v1.5.14-0.20211102124704-34db02bceed2 h1:WqWpTGAUUC07G44CsNw4WyotuqRY4nSF9xadcEC4Yrc= -github.com/caos/orbos v1.5.14-0.20211102124704-34db02bceed2/go.mod h1:/49/y2DW47eHx38cNFFTM/sd4KA5L5SjASdYBQ5lraY= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= 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= @@ -210,8 +136,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1CUzYdAZXijuvLuRMirgiXdf3zsM2Ig= github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= -github.com/cloudflare/cloudflare-go v0.23.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI= -github.com/cloudscale-ch/cloudscale-go-sdk v1.7.1/go.mod h1:FhOTOCgKAVvRRMQc1mC0D7xK/3zYnmcZBWFXNkacvMc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -227,33 +151,21 @@ github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.2.4 h1:VuiBJKut2Imgrzl+TNk+U5+GxLOh3hnIFxU0EzjTCnI= github.com/cockroachdb/cockroach-go/v2 v2.2.4/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= @@ -261,11 +173,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xb github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20211129110639-4739a1d10a51 h1:HQgSQ8RIZIhMwjefT7S2jtq99fnGHSN+BF0nkZ+myiI= github.com/dop251/goja v0.0.0-20211129110639-4739a1d10a51/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= @@ -277,12 +186,6 @@ github.com/duo-labs/webauthn v0.0.0-20211216225436-9a12cd078b8a/go.mod h1:EYSpSk github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= 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= @@ -299,33 +202,20 @@ github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= 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.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.11.0 h1:qro8uttJGvNAMr5CLcFI9CHR0aDzXl0Vs3Pmw/oTPg8= github.com/getsentry/sentry-go v0.11.0/go.mod h1:KBQIxiZAetw62Cj8Ri964vAEWVdgfaUCn30Q3bCvANo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -333,19 +223,9 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI= -github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= 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= @@ -355,19 +235,7 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb 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-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 v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM= -github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -381,9 +249,6 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 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/gobuffalo/flect v0.2.3 h1:f/ZukRnSNA/DUpSNDadko7Qc0PhGvsew35p/2tu+CRY= -github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= @@ -394,9 +259,6 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -407,7 +269,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -444,11 +305,9 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -464,18 +323,12 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo= github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -494,7 +347,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= 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= @@ -504,9 +356,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3 h1:eHv/jVY/JNop1xg2J9cBb4EzyMpWZoNCP1BslSAIkOI= github.com/googleinterns/cloud-operations-api-mock v0.0.0-20200709193332-a1e58c29bdd3/go.mod h1:h/KNeRx7oYU4SpA4SoY7W2/NxDKEEVuwA6j9A27L4OI= @@ -522,23 +371,15 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1 h1:p5m7GOEGXyoq6QWl4/RRMsQ6tWbTpbQmAnkxXgWSprY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.1/go.mod h1:8ZeZajTed/blCOHBbj8Fss8bPHiFKcmJJzuIbUtFCAo= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -552,39 +393,30 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= -github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -636,9 +468,6 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -646,14 +475,7 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/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.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -675,25 +497,19 @@ github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYb github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= -github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23/go.mod h1:kBSna6b0/RzsOcOZf515vAXwSsXYusl2U7SA0XP09yI= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7 h1:K8qael4LemsmJCGt+ccI8b0fCNFDttmEu3qtpFt3G0M= github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw= github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c h1:hnbwWED5rIu+UaMkLR3JtnscMVGqp35lfzQwLuZAAUY= github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73 h1:PSsFm2SRpq9LnaRHLz4u9ZZ3liWjgXM6OMxXE4/qlgY= github.com/kevinburke/twilio-go v0.0.0-20210327194925-1623146bcf73/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= +github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= @@ -708,15 +524,12 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 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/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/landoop/tableprinter v0.0.0-20200805134727-ea32388e35c1/go.mod h1:f0X1c0za3TbET/rl5ThtCSel0+G3/yZ8iuU9BxnyVK0= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= @@ -731,29 +544,20 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 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.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -763,10 +567,7 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= @@ -776,8 +577,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -788,27 +587,18 @@ github.com/minio/minio-go/v7 v7.0.20 h1:0+Xt1SkCKDgcx5cmo3UxXcJ37u5Gy+/2i/+eQYqm github.com/minio/minio-go/v7 v7.0.20/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2DAn1ou4+Do= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/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.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= 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= @@ -816,7 +606,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN 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/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/muesli/clusters v0.0.0-20180605185049-a07a36e67d36/go.mod h1:mw5KDqUj0eLj/6DUNINLVJNoPTFkEuGMHtJsXLviLkY= github.com/muesli/clusters v0.0.0-20200529215643-2700303c1762 h1:p4A2Jx7Lm3NV98VRMKlyWd3nqf8obft8NfXlAUmqd3I= @@ -825,11 +614,8 @@ github.com/muesli/gamut v0.2.0 h1:IZbl/hQzChTXtqDSXL8CDtjdRt58LivY03bGCm1yDyU= github.com/muesli/gamut v0.2.0/go.mod h1:kz1+UJqI1thNtocJlowyqG2o0FNsN0W534VoMVsR9/Y= github.com/muesli/kmeans v0.2.1 h1:ja5AnwfyDCVBCANrAfXr2pOh292FQnSeu1lySACDJU0= github.com/muesli/kmeans v0.2.1/go.mod h1:eNyybq0tX9/iBEP6EMU4Y7dpmGK0uEhODdZpnG1a/iQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -837,39 +623,17 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/nicksnyder/go-i18n/v2 v2.1.2 h1:QHYxcUJnGHBaq7XbvgunmZ2Pn0focXFqTD61CkH146c= github.com/nicksnyder/go-i18n/v2 v2.1.2/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= -github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= -github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= 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= @@ -880,11 +644,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= github.com/pquerna/otp v1.3.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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -895,24 +657,19 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= @@ -922,7 +679,6 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -933,8 +689,6 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -943,53 +697,39 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM= github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk= github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -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/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -999,19 +739,14 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0= github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w= github.com/ttacon/libphonenumber v1.2.1 h1:fzOfY5zUADkCkbIafAed11gL1sW+bJ26p6zWLBMElR4= github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1021,13 +756,9 @@ github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= 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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b h1:tnWgqoOBmInkt5pbLjagwNVjjT4RdJhFHzL1ebCSRh8= github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= @@ -1042,44 +773,27 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.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.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0 h1:TON1iU3Y5oIytGQHIejDYLam5uoSMsmA0UV9Yupb5gQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0/go.mod h1:T/zQwBldOpoAEpE3HMbLnI8ydESZVz4ggw6Is4FF9LI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0/go.mod h1:7W3JSDYTtH3qKKHrS1fMiwLtK7iZFLPq1+7htfspX/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0 h1:0BgiNWjN7rUWO9HdjF4L12r8OW86QkVQcYmCjnayJLo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0/go.mod h1:bdvm3YpMxWAgEfQhtTBaVR8ceXPRuRBSQrvOBnIlHxc= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ= go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0 h1:xzbcGykysUh776gzD1LUPsNNHKWN0kQWDnJhn1ddUuk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0/go.mod h1:14T5gr+Y6s2AgHPqBMgnGwp04csUjQmYXFWPeiBoq5s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0 h1:VsgsSCDwOSuO8eMVh63Cd4nACMqgjpmAeJSIvVNneD0= @@ -1091,22 +805,16 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0/go.mod h1:DUFCmFkXr go.opentelemetry.io/otel/internal/metric v0.23.0/go.mod h1:z+RPiDJe30YnCrOhFGivwBS+DU1JU/PiLKkk4re2DNY= go.opentelemetry.io/otel/internal/metric v0.25.0 h1:w/7RXe16WdPylaIXDgcYM6t/q0K5lXgSdZOEbIEyliE= go.opentelemetry.io/otel/internal/metric v0.25.0/go.mod h1:Nhuw26QSX7d6n4duoqAFi5KOQR4AuzyMcl5eXOgwxtc= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/metric v0.23.0/go.mod h1:G/Nn9InyNnIv7J6YVkQfpc0JCfKBNJaERBGw08nqmVQ= go.opentelemetry.io/otel/metric v0.25.0 h1:7cXOnCADUsR3+EOqxPaSKwhEuNu0gz/56dRN1hpIdKw= go.opentelemetry.io/otel/metric v0.25.0/go.mod h1:E884FSpQfnJOMMUaq+05IWlJ4rjZpk2s/F1Ju+TEEm8= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= go.opentelemetry.io/otel/sdk/export/metric v0.25.0 h1:6UjAFmVB5Fza3K5qUJpYWGrk8QMPIqlSnya5FI46VBY= go.opentelemetry.io/otel/sdk/export/metric v0.25.0/go.mod h1:Ej7NOa+WpN49EIcr1HMUYRvxXXCCnQCg2+ovdt2z8Pk= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/sdk/metric v0.25.0 h1:J+Ta+4IAA5W9AdWhGQLfciEpavBqqSkBzTDeYvJLFNU= go.opentelemetry.io/otel/sdk/metric v0.25.0/go.mod h1:G4xzj4LvC6xDDSsVXpvRVclQCbofGGg4ZU2VKKtDRfg= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo= go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= @@ -1115,33 +823,24 @@ go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.10.0 h1:n7brgtEbDvXEgGyKKo8SobKT1e9FewlDtXzkVP5djoE= go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -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/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1150,12 +849,9 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -1187,7 +883,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= 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= @@ -1209,7 +904,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1218,7 +912,6 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1237,7 +930,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1246,7 +938,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1254,19 +945,15 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8= +golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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-20190517181255-950ef44c6e07/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= @@ -1276,7 +963,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1301,11 +987,9 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1319,15 +1003,11 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1345,19 +1025,15 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-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-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1379,25 +1055,22 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/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-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1411,13 +1084,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1432,7 +1099,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1441,8 +1107,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1462,7 +1126,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1472,11 +1135,9 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1495,8 +1156,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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= @@ -1518,7 +1177,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1527,7 +1185,6 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6 google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= @@ -1574,7 +1231,6 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1603,11 +1259,9 @@ google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= @@ -1617,7 +1271,6 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 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= @@ -1665,34 +1318,21 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks 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-20200902074654-038fdea0a05b/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/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/raintank/schema.v1 v1.0.0/go.mod h1:mx46t/rI5UA/b+WtF5ThX+qFJ7P7MOmE3ZMR12Wfr8c= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1705,16 +1345,11 @@ 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-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg= gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1723,52 +1358,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw= -k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk= -k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nKuewd4= -k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= -k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck= -k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0= -k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= -k8s.io/cli-runtime v0.22.2/go.mod h1:tkm2YeORFpbgQHEK/igqttvPTRIHFRz5kATlw53zlMI= -k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg= -k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA= -k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= -k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M= -k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= -k8s.io/component-helpers v0.22.2/go.mod h1:+N61JAR9aKYSWbnLA88YcFr9K/6ISYvRNybX7QW7Rs8= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c h1:jvamsI1tn9V0S8jicyX82qaFC0H/NKxv2e5mbqsgR80= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kubectl v0.22.2/go.mod h1:BApg2j0edxLArCOfO0ievI27EeTQqBDMNU9VQH734iQ= -k8s.io/metrics v0.22.2/go.mod h1:GUcsBtpsqQD1tKFS/2wCKu4ZBowwRncLOJH1rgWs3uw= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.10.1/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= -sigs.k8s.io/controller-runtime v0.10.3 h1:s5Ttmw/B4AuIbwrXD3sfBkXwnPMMWrqpVj4WRt1dano= -sigs.k8s.io/controller-runtime v0.10.3/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= -sigs.k8s.io/controller-tools v0.7.0 h1:iZIz1vEcavyEfxjcTLs1WH/MPf4vhPCtTKhoHqV8/G0= -sigs.k8s.io/controller-tools v0.7.0/go.mod h1:bpBAo0VcSDDLuWt47evLhMLPxRPxMDInTEH/YbdeMK0= -sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g= -sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs= -sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go= -sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt deleted file mode 100644 index 767efde981..0000000000 --- a/hack/boilerplate.go.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - - -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. -*/ \ No newline at end of file diff --git a/operator/adapt.go b/operator/adapt.go deleted file mode 100644 index 6f0a3bbac4..0000000000 --- a/operator/adapt.go +++ /dev/null @@ -1,129 +0,0 @@ -package operator - -import ( - "fmt" - - "gopkg.in/yaml.v3" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" -) - -type AdaptFunc func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, -) ( - QueryFunc, - DestroyFunc, - ConfigureFunc, - map[string]*secret.Secret, - map[string]*secret.Existing, - bool, - error, -) - -type EnsureFunc func(k8sClient kubernetes.ClientInt) error - -type DestroyFunc func(k8sClient kubernetes.ClientInt) error - -type ConfigureFunc func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, gitops bool) error - -type QueryFunc func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (EnsureFunc, error) - -func Parse(gitClient *git.Client, file string) (*tree.Tree, error) { - if err := gitClient.Clone(); err != nil { - return nil, err - } - - tree := &tree.Tree{} - if err := yaml.Unmarshal(gitClient.Read(file), tree); err != nil { - return nil, err - } - - return tree, nil -} - -func ResourceDestroyToZitadelDestroy(destroyFunc resources.DestroyFunc) DestroyFunc { - return func(k8sClient kubernetes.ClientInt) error { - return destroyFunc(k8sClient) - } -} - -func ResourceQueryToZitadelQuery(queryFunc resources.QueryFunc) QueryFunc { - return func(k8sClient kubernetes.ClientInt, _ map[string]interface{}) (EnsureFunc, error) { - ensure, err := queryFunc(k8sClient) - ensureInternal := ResourceEnsureToZitadelEnsure(ensure) - - return func(k8sClient kubernetes.ClientInt) error { - return ensureInternal(k8sClient) - }, err - } -} - -func ResourceEnsureToZitadelEnsure(ensureFunc resources.EnsureFunc) EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - return ensureFunc(k8sClient) - } -} -func EnsureFuncToQueryFunc(ensure EnsureFunc) QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (ensureFunc EnsureFunc, err error) { - return ensure, err - } -} - -func QueriersToEnsureFunc(monitor mntr.Monitor, infoLogs bool, queriers []QueryFunc, k8sClient kubernetes.ClientInt, queried map[string]interface{}) (EnsureFunc, error) { - if infoLogs { - monitor.Info("querying...") - } else { - monitor.Debug("querying...") - } - ensurers := make([]EnsureFunc, 0) - for _, querier := range queriers { - ensurer, err := querier(k8sClient, queried) - if err != nil { - return nil, fmt.Errorf("error while querying: %w", err) - } - ensurers = append(ensurers, ensurer) - } - if infoLogs { - monitor.Info("queried") - } else { - monitor.Debug("queried") - } - return func(k8sClient kubernetes.ClientInt) error { - if infoLogs { - monitor.Info("ensuring...") - } else { - monitor.Debug("ensuring...") - } - for _, ensurer := range ensurers { - if err := ensurer(k8sClient); err != nil { - return fmt.Errorf("error while ensuring: %w", err) - } - } - if infoLogs { - monitor.Info("ensured") - } else { - monitor.Debug("ensured") - } - return nil - }, nil -} - -func DestroyersToDestroyFunc(monitor mntr.Monitor, destroyers []DestroyFunc) DestroyFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("destroying...") - for _, destroyer := range destroyers { - if err := destroyer(k8sClient); err != nil { - return fmt.Errorf("error while destroying: %w", err) - } - } - monitor.Info("destroyed") - return nil - } -} diff --git a/operator/api/core/api.go b/operator/api/core/api.go deleted file mode 100644 index b57d269a45..0000000000 --- a/operator/api/core/api.go +++ /dev/null @@ -1,46 +0,0 @@ -package core - -import ( - "errors" - - "github.com/caos/orbos/pkg/tree" - "gopkg.in/yaml.v3" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func UnmarshalUnstructuredSpec(unstruct *unstructured.Unstructured) (*tree.Tree, error) { - spec, found := unstruct.Object["spec"] - if !found { - return nil, errors.New("no spec in crd") - } - specMap, ok := spec.(map[string]interface{}) - if !ok { - return nil, errors.New("no spec in crd") - } - - data, err := yaml.Marshal(specMap) - if err != nil { - return nil, err - } - - desired := &tree.Tree{} - if err := yaml.Unmarshal(data, &desired); err != nil { - return nil, err - } - - return desired, nil -} - -func MarshalToUnstructuredSpec(t *tree.Tree) (*unstructured.Unstructured, error) { - data, err := yaml.Marshal(t) - if err != nil { - return nil, err - } - - unstruct := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "spec": make(map[string]interface{}), - }, - } - return unstruct, yaml.Unmarshal(data, unstruct.Object["spec"]) -} diff --git a/operator/api/database/api.go b/operator/api/database/api.go deleted file mode 100644 index 7db8431904..0000000000 --- a/operator/api/database/api.go +++ /dev/null @@ -1,44 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/core" - databasev1 "github.com/caos/zitadel/operator/api/database/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" -) - -const ( - Namespace = "caos-system" - kind = "Database" - apiVersion = "caos.ch/v1" - Name = "database" -) - -func ReadCrd(k8sClient kubernetes.ClientInt) (*tree.Tree, error) { - unstruct, err := k8sClient.GetNamespacedCRDResource(databasev1.GroupVersion.Group, databasev1.GroupVersion.Version, kind, Namespace, Name) - if err != nil { - if macherrs.IsNotFound(err) || meta.IsNoMatchError(err) { - return nil, nil - } - return nil, err - } - - return core.UnmarshalUnstructuredSpec(unstruct) -} - -func WriteCrd(k8sClient kubernetes.ClientInt, t *tree.Tree) error { - - unstruct, err := core.MarshalToUnstructuredSpec(t) - if err != nil { - return err - } - - unstruct.SetName(Name) - unstruct.SetNamespace(Namespace) - unstruct.SetKind(kind) - unstruct.SetAPIVersion(apiVersion) - - return k8sClient.ApplyNamespacedCRDResource(databasev1.GroupVersion.Group, databasev1.GroupVersion.Version, kind, Namespace, Name, unstruct) -} diff --git a/operator/api/database/v1/database.go b/operator/api/database/v1/database.go deleted file mode 100644 index 569dc07984..0000000000 --- a/operator/api/database/v1/database.go +++ /dev/null @@ -1,57 +0,0 @@ -// +kubebuilder:object:generate=true -// +groupName=caos.ch -package v1 - -import ( - "github.com/caos/orbos/pkg/tree" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} - - // AddToScheme adds the types in this group-version to the given scheme. - AddToScheme = SchemeBuilder.AddToScheme -) - -// +kubebuilder:storageversion -// +kubebuilder:object:root=true -// +kubebuilder:crd=Database -type Database struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec Spec `json:"spec,omitempty"` - Status Status `json:"status,omitempty"` -} - -type Status struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} - -type Spec struct { - Common *tree.Common `json:",inline" yaml:",inline"` - Spec *orbdb.Spec `json:"spec" yaml:"spec"` - Database *Empty `json:"database" yaml:"database"` -} - -type Empty struct{} - -// +kubebuilder:object:root=true -type DatabaseList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Database `json:"items"` -} - -func init() { - SchemeBuilder.Register(&Database{}, &DatabaseList{}) -} diff --git a/operator/api/database/v1/zz_generated.deepcopy.go b/operator/api/database/v1/zz_generated.deepcopy.go deleted file mode 100644 index c97c16b038..0000000000 --- a/operator/api/database/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,146 +0,0 @@ -// +build !ignore_autogenerated - -/* - - -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. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package v1 - -import ( - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/orb" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Database) DeepCopyInto(out *Database) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. -func (in *Database) DeepCopy() *Database { - if in == nil { - return nil - } - out := new(Database) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Database) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DatabaseList) DeepCopyInto(out *DatabaseList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Database, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseList. -func (in *DatabaseList) DeepCopy() *DatabaseList { - if in == nil { - return nil - } - out := new(DatabaseList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DatabaseList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Empty) DeepCopyInto(out *Empty) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. -func (in *Empty) DeepCopy() *Empty { - if in == nil { - return nil - } - out := new(Empty) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Spec) DeepCopyInto(out *Spec) { - *out = *in - if in.Common != nil { - in, out := &in.Common, &out.Common - *out = new(tree.Common) - **out = **in - } - if in.Spec != nil { - in, out := &in.Spec, &out.Spec - *out = new(orb.Spec) - (*in).DeepCopyInto(*out) - } - if in.Database != nil { - in, out := &in.Database, &out.Database - *out = new(Empty) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. -func (in *Spec) DeepCopy() *Spec { - if in == nil { - return nil - } - out := new(Spec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Status) DeepCopyInto(out *Status) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. -func (in *Status) DeepCopy() *Status { - if in == nil { - return nil - } - out := new(Status) - in.DeepCopyInto(out) - return out -} diff --git a/operator/api/zitadel/api.go b/operator/api/zitadel/api.go deleted file mode 100644 index 32cff71582..0000000000 --- a/operator/api/zitadel/api.go +++ /dev/null @@ -1,44 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/core" - zitadelv1 "github.com/caos/zitadel/operator/api/zitadel/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" -) - -const ( - Namespace = "caos-system" - kind = "Zitadel" - apiVersion = "caos.ch/v1" - Name = "zitadel" -) - -func ReadCrd(k8sClient kubernetes.ClientInt) (*tree.Tree, error) { - unstruct, err := k8sClient.GetNamespacedCRDResource(zitadelv1.GroupVersion.Group, zitadelv1.GroupVersion.Version, kind, Namespace, Name) - if err != nil { - if macherrs.IsNotFound(err) || meta.IsNoMatchError(err) { - return nil, nil - } - return nil, err - } - - return core.UnmarshalUnstructuredSpec(unstruct) -} - -func WriteCrd(k8sClient kubernetes.ClientInt, t *tree.Tree) error { - - unstruct, err := core.MarshalToUnstructuredSpec(t) - if err != nil { - return err - } - - unstruct.SetName(Name) - unstruct.SetNamespace(Namespace) - unstruct.SetKind(kind) - unstruct.SetAPIVersion(apiVersion) - - return k8sClient.ApplyNamespacedCRDResource(zitadelv1.GroupVersion.Group, zitadelv1.GroupVersion.Version, kind, Namespace, Name, unstruct) -} diff --git a/operator/api/zitadel/v1/zitadel.go b/operator/api/zitadel/v1/zitadel.go deleted file mode 100644 index 22e1135ba1..0000000000 --- a/operator/api/zitadel/v1/zitadel.go +++ /dev/null @@ -1,57 +0,0 @@ -// +kubebuilder:object:generate=true -// +groupName=caos.ch -package v1 - -import ( - "github.com/caos/orbos/pkg/tree" - orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "caos.ch", Version: "v1"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} - - // AddToScheme adds the types in this group-version to the given scheme. - AddToScheme = SchemeBuilder.AddToScheme -) - -// +kubebuilder:storageversion -// +kubebuilder:object:root=true -// +kubebuilder:crd=Zitadel -type Zitadel struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec Spec `json:"spec,omitempty"` - Status Status `json:"status,omitempty"` -} - -type Status struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} - -type Spec struct { - Common *tree.Common `json:",inline" yaml:",inline"` - Spec *orbz.Spec `json:"spec" yaml:"spec"` - IAM *Empty `json:"iam" yaml:"iam"` -} - -type Empty struct{} - -// +kubebuilder:object:root=true -type ZitadelList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Zitadel `json:"items"` -} - -func init() { - SchemeBuilder.Register(&Zitadel{}, &ZitadelList{}) -} diff --git a/operator/api/zitadel/v1/zz_generated.deepcopy.go b/operator/api/zitadel/v1/zz_generated.deepcopy.go deleted file mode 100644 index f9a3bc874b..0000000000 --- a/operator/api/zitadel/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,146 +0,0 @@ -// +build !ignore_autogenerated - -/* - - -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. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package v1 - -import ( - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Empty) DeepCopyInto(out *Empty) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Empty. -func (in *Empty) DeepCopy() *Empty { - if in == nil { - return nil - } - out := new(Empty) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Spec) DeepCopyInto(out *Spec) { - *out = *in - if in.Common != nil { - in, out := &in.Common, &out.Common - *out = new(tree.Common) - **out = **in - } - if in.Spec != nil { - in, out := &in.Spec, &out.Spec - *out = new(orb.Spec) - (*in).DeepCopyInto(*out) - } - if in.IAM != nil { - in, out := &in.IAM, &out.IAM - *out = new(Empty) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. -func (in *Spec) DeepCopy() *Spec { - if in == nil { - return nil - } - out := new(Spec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Status) DeepCopyInto(out *Status) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. -func (in *Status) DeepCopy() *Status { - if in == nil { - return nil - } - out := new(Status) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Zitadel) DeepCopyInto(out *Zitadel) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Zitadel. -func (in *Zitadel) DeepCopy() *Zitadel { - if in == nil { - return nil - } - out := new(Zitadel) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Zitadel) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ZitadelList) DeepCopyInto(out *ZitadelList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Zitadel, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZitadelList. -func (in *ZitadelList) DeepCopy() *ZitadelList { - if in == nil { - return nil - } - out := new(ZitadelList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ZitadelList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/operator/common/images.go b/operator/common/images.go deleted file mode 100644 index f9acef3aa8..0000000000 --- a/operator/common/images.go +++ /dev/null @@ -1,46 +0,0 @@ -package common - -type image string - -func (i image) String() string { return string(i) } - -type dockerhubImage image - -type zitadelImage image - -const ( - CockroachImage dockerhubImage = "cockroachdb/cockroach:v21.2.5" - PostgresImage dockerhubImage = "postgres:9.6.17" - FlywayImage dockerhubImage = "flyway/flyway:8.0.2" - AlpineImage dockerhubImage = "alpine:3.11" - ZITADELImage zitadelImage = "caos/zitadel" - BackupImage zitadelImage = "caos/zitadel-crbackup" - ZITADELOperatorImage zitadelImage = "caos/zitadel-operator" -) - -func (z zitadelImage) Reference(customImageRegistry, version string) string { - - reg := "ghcr.io" - if customImageRegistry != "" { - reg = customImageRegistry - } - - return concat(image(z), reg, version) -} - -func (d dockerhubImage) Reference(customImageRegistry string) string { - return concat(image(d), customImageRegistry, "") -} - -func concat(img image, customImageRegistry, version string) string { - str := img.String() - - if customImageRegistry != "" { - str = customImageRegistry + "/" + str - } - - if version != "" { - str = str + ":" + version - } - return str -} diff --git a/operator/common/images_test.go b/operator/common/images_test.go deleted file mode 100644 index 799c79da31..0000000000 --- a/operator/common/images_test.go +++ /dev/null @@ -1,106 +0,0 @@ -package common - -import ( - "errors" - "fmt" - "strings" - "testing" -) - -func TestDockerHubReference(t *testing.T) { - - imgs := []dockerhubImage{CockroachImage, PostgresImage, FlywayImage, AlpineImage} - - type args struct { - customImageRegistry string - } - tests := []struct { - name string - args args - test func(result string) error - }{{ - name: "Image should be pulled from docker hub by default", - args: args{ - customImageRegistry: "", - }, - test: func(result string) error { - return expectRegistry(result, "") - }, - }, { - name: "Given a custom image registry, the registry should be prepended", - args: args{ - customImageRegistry: "myreg.io", - }, - test: func(result string) error { - return expectRegistry(result, "myreg.io") - }, - }} - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - for i := range imgs { - got := imgs[i].Reference(tt.args.customImageRegistry) - if err := tt.test(got); err != nil { - t.Error(fmt.Errorf("DockerHubReference(%s): %w", imgs[i], err)) - } - } - }) - } -} - -func TestZITADELReference(t *testing.T) { - - imgs := []zitadelImage{ZITADELImage, BackupImage} - dummyVersion := "v99.99.99" - - type args struct { - customImageRegistry string - } - tests := []struct { - name string - args args - test func(result string) error - }{{ - name: "Image should be pulled from GHCR by default", - args: args{ - customImageRegistry: "", - }, - test: func(result string) error { - return expectRegistry(result, "ghcr.io/") - }, - }, { - name: "Given a random docker hub image and a custom image registry, the registry should be prepended", - args: args{ - customImageRegistry: "myreg.io", - }, - test: func(result string) error { - return expectRegistry(result, "myreg.io") - }, - }} - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - for i := range imgs { - got := imgs[i].Reference(tt.args.customImageRegistry, dummyVersion) - if err := tt.test(got); err != nil { - t.Error(fmt.Errorf("ZITADELReference(%s): %w", imgs[i], err)) - } - } - }) - } -} - -func expectRegistry(result, expect string) error { - if !strings.HasPrefix(result, expect) { - return fmt.Errorf("image is not prefixed by the registry %s", expect) - } - points := strings.Count(result[:strings.Index(result, ":")], ".") - if expect == "" && points > 1 { - return errors.New("doesn't look like a docker image") - } - - if points > 1 { - return errors.New("too many points") - } - return nil -} diff --git a/operator/common/yaml.go b/operator/common/yaml.go deleted file mode 100644 index 1745a932a9..0000000000 --- a/operator/common/yaml.go +++ /dev/null @@ -1,25 +0,0 @@ -package common - -import ( - "bytes" - "gopkg.in/yaml.v3" -) - -func MarshalYAML(sth interface{}) []byte { - if sth == nil { - return nil - } - buf := new(bytes.Buffer) - encoder := yaml.NewEncoder(buf) - - defer func() { - encoder.Close() - buf.Truncate(0) - }() - - encoder.SetIndent(2) - if err := encoder.Encode(sth); err != nil { - panic(err) - } - return buf.Bytes() -} diff --git a/operator/crtlcrd/backup.go b/operator/crtlcrd/backup.go deleted file mode 100644 index 6976f88387..0000000000 --- a/operator/crtlcrd/backup.go +++ /dev/null @@ -1,27 +0,0 @@ -package crtlcrd - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/pkg/databases" -) - -func Restore( - monitor mntr.Monitor, - k8sClient *kubernetes.Client, - backup string, -) error { - if err := databases.CrdClear(monitor, k8sClient); err != nil { - return err - } - - if err := databases.CrdRestore( - monitor, - k8sClient, - backup, - ); err != nil { - return err - } - - return nil -} diff --git a/operator/crtlcrd/controller.go b/operator/crtlcrd/controller.go deleted file mode 100644 index c120fa4289..0000000000 --- a/operator/crtlcrd/controller.go +++ /dev/null @@ -1,80 +0,0 @@ -package crtlcrd - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - - databasev1 "github.com/caos/zitadel/operator/api/database/v1" - zitadelv1 "github.com/caos/zitadel/operator/api/zitadel/v1" - "github.com/caos/zitadel/operator/crtlcrd/database" - "github.com/caos/zitadel/operator/crtlcrd/zitadel" -) - -const ( - Database = "database" - Zitadel = "zitadel" -) - -var ( - scheme = runtime.NewScheme() -) - -func init() { - _ = clientgoscheme.AddToScheme(scheme) - - _ = databasev1.AddToScheme(scheme) - _ = zitadelv1.AddToScheme(scheme) -} - -func Start(monitor mntr.Monitor, version, metricsAddr string, features ...string) error { - cfg := ctrl.GetConfigOrDie() - mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - LeaderElection: false, - LeaderElectionID: "9adsd12l.caos.ch", - }) - if err != nil { - return fmt.Errorf("unable to start manager: %w", err) - } - - k8sClient, err := kubernetes.NewK8sClientWithConfig(monitor, cfg) - if err != nil { - return err - } - - for _, feature := range features { - switch feature { - case Database: - if err = (&database.Reconciler{ - ClientInt: k8sClient, - Monitor: monitor, - Scheme: mgr.GetScheme(), - Version: version, - }).SetupWithManager(mgr); err != nil { - return fmt.Errorf("unable to create controller: %w", err) - } - case Zitadel: - if err = (&zitadel.Reconciler{ - ClientInt: k8sClient, - Monitor: monitor, - Scheme: mgr.GetScheme(), - Version: version, - }).SetupWithManager(mgr); err != nil { - return fmt.Errorf("unable to create controller: %w", err) - } - } - } - - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { - return fmt.Errorf("problem running manager: %w", err) - } - return nil -} diff --git a/operator/crtlcrd/database/database.go b/operator/crtlcrd/database/database.go deleted file mode 100644 index 99fc1504f6..0000000000 --- a/operator/crtlcrd/database/database.go +++ /dev/null @@ -1,68 +0,0 @@ -package database - -import ( - "context" - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - v1 "github.com/caos/zitadel/operator/api/database/v1" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" -) - -type Reconciler struct { - kubernetes.ClientInt - Monitor mntr.Monitor - Scheme *runtime.Scheme - Version string -} - -func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) { - internalMonitor := r.Monitor.WithFields(map[string]interface{}{ - "kind": "database", - "namespace": req.NamespacedName, - }) - - defer func() { - r.Monitor.Error(err) - }() - - if req.Namespace != database.Namespace || req.Name != database.Name { - return res, fmt.Errorf("resource must be named %s and namespaced in %s", database.Name, database.Namespace) - } - - desired, err := database.ReadCrd(r.ClientInt) - if err != nil { - internalMonitor.Error(err) - return res, err - } - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", &r.Version, false, "database")(internalMonitor, desired, &tree.Tree{}) - if err != nil { - internalMonitor.Error(err) - return res, err - } - - ensure, err := query(r.ClientInt, map[string]interface{}{}) - if err != nil { - internalMonitor.Error(err) - return res, err - } - - if err := ensure(r.ClientInt); err != nil { - internalMonitor.Error(err) - return res, err - } - - return res, nil -} - -func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&v1.Database{}). - Complete(r) -} diff --git a/operator/crtlcrd/database/destroy.go b/operator/crtlcrd/database/destroy.go deleted file mode 100644 index 2eaf948011..0000000000 --- a/operator/crtlcrd/database/destroy.go +++ /dev/null @@ -1,26 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return err - } - - if desired != nil { - _, destroy, _, _, _, _, err := orbdb.AdaptFunc("", &version, false, "database")(monitor, desired, &tree.Tree{}) - if err != nil { - return err - } - - return destroy(k8sClient) - } - return nil -} diff --git a/operator/crtlcrd/destroy.go b/operator/crtlcrd/destroy.go deleted file mode 100644 index 857ff654e2..0000000000 --- a/operator/crtlcrd/destroy.go +++ /dev/null @@ -1,24 +0,0 @@ -package crtlcrd - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator/crtlcrd/database" - "github.com/caos/zitadel/operator/crtlcrd/zitadel" -) - -func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string, features ...string) error { - for _, feature := range features { - switch feature { - case Zitadel: - if err := zitadel.Destroy(monitor, k8sClient, version); err != nil { - return err - } - case Database: - if err := database.Destroy(monitor, k8sClient, version); err != nil { - return err - } - } - } - return nil -} diff --git a/operator/crtlcrd/zitadel/destroy.go b/operator/crtlcrd/zitadel/destroy.go deleted file mode 100644 index 7f4a442278..0000000000 --- a/operator/crtlcrd/zitadel/destroy.go +++ /dev/null @@ -1,26 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/zitadel" - orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" -) - -func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string) error { - desired, err := zitadel.ReadCrd(k8sClient) - if err != nil { - return err - } - - if desired != nil { - _, destroy, _, _, _, _, err := orbz.AdaptFunc(nil, "ensure", &version, false, []string{"operator", "iam"})(monitor, desired, &tree.Tree{}) - if err != nil { - return err - } - - return destroy(k8sClient) - } - return nil -} diff --git a/operator/crtlcrd/zitadel/scale.go b/operator/crtlcrd/zitadel/scale.go deleted file mode 100644 index 8487cb72c8..0000000000 --- a/operator/crtlcrd/zitadel/scale.go +++ /dev/null @@ -1,32 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" - macherrs "k8s.io/apimachinery/pkg/api/errors" -) - -func ScaleDown( - monitor mntr.Monitor, - k8sClient *kubernetes.Client, - version *string, -) (bool, error) { - noZitadel := false - if err := Takeoff(monitor, k8sClient, orb.AdaptFunc(nil, "scaledown", version, false, []string{"scaledown"})); err != nil { - if macherrs.IsNotFound(err) { - noZitadel = true - } else { - return noZitadel, err - } - } - return noZitadel, nil -} - -func ScaleUp( - monitor mntr.Monitor, - k8sClient *kubernetes.Client, - version *string, -) error { - return Takeoff(monitor, k8sClient, orb.AdaptFunc(nil, "scaleup", version, false, []string{"scaleup"})) -} diff --git a/operator/crtlcrd/zitadel/zitadel.go b/operator/crtlcrd/zitadel/zitadel.go deleted file mode 100644 index 4bb196d070..0000000000 --- a/operator/crtlcrd/zitadel/zitadel.go +++ /dev/null @@ -1,77 +0,0 @@ -package zitadel - -import ( - "context" - "fmt" - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/zitadel" - v1 "github.com/caos/zitadel/operator/api/zitadel/v1" - orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" -) - -type Reconciler struct { - kubernetes.ClientInt - Monitor mntr.Monitor - Scheme *runtime.Scheme - Version string -} - -func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) { - internalMonitor := r.Monitor.WithFields(map[string]interface{}{ - "kind": "zitadel", - "namespace": req.NamespacedName, - }) - - defer func() { - r.Monitor.Error(err) - }() - - if req.Namespace != zitadel.Namespace || req.Name != zitadel.Name { - return res, fmt.Errorf("resource must be named %s and namespaced in %s", zitadel.Name, zitadel.Namespace) - } - - if err := Takeoff(internalMonitor, r.ClientInt, orbz.AdaptFunc(nil, "ensure", &r.Version, false, []string{"operator", "iam"})); err != nil { - return res, err - } - - return res, nil -} - -func Takeoff( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - adaptFunc operator.AdaptFunc, -) error { - desired, err := zitadel.ReadCrd(k8sClient) - if err != nil { - return err - } - - query, _, _, _, _, _, err := adaptFunc(monitor, desired, &tree.Tree{}) - if err != nil { - return err - } - - ensure, err := query(k8sClient, map[string]interface{}{}) - if err != nil { - return err - } - - if err := ensure(k8sClient); err != nil { - return err - } - - return nil -} - -func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&v1.Zitadel{}). - Complete(r) -} diff --git a/operator/crtlgitops/backup.go b/operator/crtlgitops/backup.go deleted file mode 100644 index 34755b7959..0000000000 --- a/operator/crtlgitops/backup.go +++ /dev/null @@ -1,29 +0,0 @@ -package crtlgitops - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/pkg/databases" -) - -func Restore( - monitor mntr.Monitor, - gitClient *git.Client, - k8sClient *kubernetes.Client, - backup string, -) error { - if err := databases.GitOpsClear(monitor, k8sClient, gitClient); err != nil { - return err - } - - if err := databases.GitOpsRestore( - monitor, - k8sClient, - gitClient, - backup, - ); err != nil { - return err - } - return nil -} diff --git a/operator/crtlgitops/destroy.go b/operator/crtlgitops/destroy.go deleted file mode 100644 index 44c6ca3ba2..0000000000 --- a/operator/crtlgitops/destroy.go +++ /dev/null @@ -1,44 +0,0 @@ -package crtlgitops - -import ( - "context" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - orbconfig "github.com/caos/orbos/pkg/orb" - "github.com/caos/zitadel/operator/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" - "github.com/caos/zitadel/operator/zitadel" - orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" -) - -func DestroyOperator(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { - - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) - if err != nil { - return err - } - - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - return err - } - - return zitadel.Destroy(monitor, gitClient, orbz.AdaptFunc(orbConfig, "ensure", version, gitops, []string{"zitadel", "iam"}), k8sClient) -} - -func DestroyDatabase(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { - - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) - if err != nil { - return err - } - - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - return err - } - - return database.Destroy(monitor, gitClient, orbdb.AdaptFunc("", version, gitops, "operator", "database", "backup"), k8sClient) -} diff --git a/operator/crtlgitops/scale.go b/operator/crtlgitops/scale.go deleted file mode 100644 index 980edf8238..0000000000 --- a/operator/crtlgitops/scale.go +++ /dev/null @@ -1,41 +0,0 @@ -package crtlgitops - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - orbconfig "github.com/caos/orbos/pkg/orb" - "github.com/caos/zitadel/operator/zitadel" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" - macherrs "k8s.io/apimachinery/pkg/api/errors" -) - -func ScaleDown( - monitor mntr.Monitor, - gitClient *git.Client, - k8sClient *kubernetes.Client, - orbCfg *orbconfig.Orb, - version *string, - gitops bool, -) (bool, error) { - noZitadel := false - if err := zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbCfg, "scaledown", version, gitops, []string{"scaledown"}), k8sClient)(); err != nil { - if macherrs.IsNotFound(err) { - noZitadel = true - } else { - return noZitadel, err - } - } - return noZitadel, nil -} - -func ScaleUp( - monitor mntr.Monitor, - gitClient *git.Client, - k8sClient *kubernetes.Client, - orbCfg *orbconfig.Orb, - version *string, - gitops bool, -) error { - return zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbCfg, "scaleup", version, gitops, []string{"scaleup"}), k8sClient)() -} diff --git a/operator/crtlgitops/start.go b/operator/crtlgitops/start.go deleted file mode 100644 index 4561403881..0000000000 --- a/operator/crtlgitops/start.go +++ /dev/null @@ -1,90 +0,0 @@ -package crtlgitops - -import ( - "context" - "time" - - "github.com/caos/zitadel/operator/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" - "github.com/caos/zitadel/operator/zitadel" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - orbconfig "github.com/caos/orbos/pkg/orb" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" -) - -func Operator(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { - takeoffChan := make(chan struct{}) - go func() { - takeoffChan <- struct{}{} - }() - - for range takeoffChan { - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) - if err != nil { - monitor.Error(err) - return err - } - - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - monitor.Error(err) - return err - } - - takeoff := zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbConfig, "ensure", version, gitops, []string{"operator", "iam"}), k8sClient) - - go func() { - started := time.Now() - takeoff() - - monitor.WithFields(map[string]interface{}{ - "took": time.Since(started), - }).Info("Iteration done") - - time.Sleep(time.Second * 10) - takeoffChan <- struct{}{} - }() - } - - return nil -} - -func Database(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, binaryVersion *string, gitops bool) error { - takeoffChan := make(chan struct{}) - go func() { - takeoffChan <- struct{}{} - }() - - for range takeoffChan { - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) - if err != nil { - monitor.Error(err) - return err - } - - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - monitor.Error(err) - return err - } - - takeoff := database.Takeoff(monitor, gitClient, orbdb.AdaptFunc("", binaryVersion, gitops, "operator", "database", "backup"), k8sClient) - - go func() { - started := time.Now() - takeoff() - - monitor.WithFields(map[string]interface{}{ - "took": time.Since(started), - }).Info("Iteration done") - - time.Sleep(time.Second * 10) - takeoffChan <- struct{}{} - }() - } - - return nil -} diff --git a/operator/database/destroy.go b/operator/database/destroy.go deleted file mode 100644 index cd65f6b6e0..0000000000 --- a/operator/database/destroy.go +++ /dev/null @@ -1,34 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" -) - -func Destroy( - monitor mntr.Monitor, - gitClient *git.Client, - adapt operator.AdaptFunc, - k8sClient *kubernetes.Client, -) error { - internalMonitor := monitor.WithField("operator", "database") - internalMonitor.Info("Destroy") - treeDesired, err := operator.Parse(gitClient, "database.yml") - if err != nil { - return err - } - treeCurrent := &tree.Tree{} - - _, destroy, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) - if err != nil { - return err - } - - if err := destroy(k8sClient); err != nil { - return err - } - return nil -} diff --git a/operator/database/kinds/backups/backups.go b/operator/database/kinds/backups/backups.go deleted file mode 100644 index 65b39d0598..0000000000 --- a/operator/database/kinds/backups/backups.go +++ /dev/null @@ -1,107 +0,0 @@ -package backups - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket" - "github.com/caos/zitadel/operator/database/kinds/backups/s3" - corev1 "k8s.io/api/core/v1" -) - -func Adapt( - monitor mntr.Monitor, - desiredTree *tree.Tree, - currentTree *tree.Tree, - name string, - namespace string, - componentLabels *labels.Component, - checkDBReady operator.EnsureFunc, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - version string, - dbURL string, - dbPort int32, - features []string, - customImageRegistry string, -) ( - operator.QueryFunc, - operator.DestroyFunc, - operator.ConfigureFunc, - map[string]*secret.Secret, - map[string]*secret.Existing, - bool, - error, -) { - switch desiredTree.Common.Kind { - case "databases.caos.ch/BucketBackup": - return bucket.AdaptFunc( - name, - namespace, - labels.MustForComponent( - labels.MustReplaceAPI( - labels.GetAPIFromComponent(componentLabels), - "BucketBackup", - desiredTree.Common.Version(), - ), - "backup"), - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - customImageRegistry, - )(monitor, desiredTree, currentTree) - case "databases.caos.ch/S3Backup": - return s3.AdaptFunc( - name, - namespace, - labels.MustForComponent( - labels.MustReplaceAPI( - labels.GetAPIFromComponent(componentLabels), - "S3Backup", - desiredTree.Common.Version(), - ), - "backup"), - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - customImageRegistry, - )(monitor, desiredTree, currentTree) - default: - return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind)) - } -} - -func GetBackupList( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - name string, - desiredTree *tree.Tree, -) ( - []string, - error, -) { - switch desiredTree.Common.Kind { - case "databases.caos.ch/BucketBackup": - return bucket.BackupList()(monitor, k8sClient, name, desiredTree) - case "databases.caos.ch/S3Backup": - return s3.BackupList()(monitor, k8sClient, name, desiredTree) - default: - return nil, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind)) - } -} diff --git a/operator/database/kinds/backups/bucket/adapt.go b/operator/database/kinds/backups/bucket/adapt.go deleted file mode 100644 index 184a8c0865..0000000000 --- a/operator/database/kinds/backups/bucket/adapt.go +++ /dev/null @@ -1,279 +0,0 @@ -package bucket - -import ( - "fmt" - - corev1 "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/secret" - "github.com/caos/orbos/pkg/labels" - secretpkg "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/secret/read" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/common" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" -) - -const ( - secretName = "backup-serviceaccountjson" - secretKey = "serviceaccountjson" -) - -func AdaptFunc( - name string, - namespace string, - componentLabels *labels.Component, - checkDBReady operator.EnsureFunc, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - version string, - dbURL string, - dbPort int32, - features []string, - customImageRegistry string, -) operator.AdaptFunc { - return func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, - ) ( - operator.QueryFunc, - operator.DestroyFunc, - operator.ConfigureFunc, - map[string]*secretpkg.Secret, - map[string]*secretpkg.Existing, - bool, - error, - ) { - - internalMonitor := monitor.WithField("component", "backup") - - desiredKind, err := ParseDesiredV0(desired) - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - secrets, existing := getSecretsMap(desiredKind) - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - internalMonitor.Verbose() - } - - destroyS, err := secret.AdaptFuncToDestroy(namespace, secretName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - image := common.BackupImage.Reference(customImageRegistry, version) - - _, destroyB, err := backup.AdaptFunc( - internalMonitor, - name, - namespace, - componentLabels, - checkDBReady, - desiredKind.Spec.Bucket, - desiredKind.Spec.Cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - _, destroyR, err := restore.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - desiredKind.Spec.Bucket, - timestamp, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - dbURL, - dbPort, - image, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - /*_, destroyC, err := clean.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - []string{}, - []string{}, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - image, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - }*/ - - destroyers := make([]operator.DestroyFunc, 0) - for _, feature := range features { - switch feature { - case backup.Normal, backup.Instant: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyS), - destroyB, - ) - /*case clean.Instant: - destroyers = append(destroyers, - destroyC, - )*/ - case restore.Instant: - destroyers = append(destroyers, - destroyR, - ) - } - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - - if err := desiredKind.validateSecrets(); err != nil { - return nil, err - } - - value, err := read.GetSecretValue(k8sClient, desiredKind.Spec.ServiceAccountJSON, desiredKind.Spec.ExistingServiceAccountJSON) - if err != nil { - return nil, err - } - - queryS, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, secretName), map[string]string{secretKey: value}) - if err != nil { - return nil, err - } - - queryB, _, err := backup.AdaptFunc( - internalMonitor, - name, - namespace, - componentLabels, - checkDBReady, - desiredKind.Spec.Bucket, - desiredKind.Spec.Cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - if err != nil { - return nil, err - } - - queryR, _, err := restore.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - desiredKind.Spec.Bucket, - timestamp, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - dbURL, - dbPort, - image, - ) - if err != nil { - return nil, err - } - - /*queryC, _, err := clean.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - databases, - users, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - image, - ) - if err != nil { - return nil, err - }*/ - - queriers := make([]operator.QueryFunc, 0) - cleanupQueries := make([]operator.QueryFunc, 0) - for _, feature := range features { - switch feature { - case backup.Normal: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryS), - queryB, - ) - case backup.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryS), - queryB, - ) - cleanupQueries = append(cleanupQueries, - operator.EnsureFuncToQueryFunc(backup.GetCleanupFunc(monitor, namespace, name)), - ) - /*case clean.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryS), - queryC, - ) - cleanupQueries = append(cleanupQueries, - operator.EnsureFuncToQueryFunc(clean.GetCleanupFunc(monitor, namespace, name)), - )*/ - case restore.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryS), - queryR, - ) - cleanupQueries = append(cleanupQueries, - operator.EnsureFuncToQueryFunc(restore.GetCleanupFunc(monitor, namespace, name)), - ) - } - } - - for _, cleanup := range cleanupQueries { - queriers = append(queriers, cleanup) - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - func(kubernetes.ClientInt, map[string]interface{}, bool) error { return nil }, - secrets, - existing, - false, - nil - } -} diff --git a/operator/database/kinds/backups/bucket/adapt_test.go b/operator/database/kinds/backups/bucket/adapt_test.go deleted file mode 100644 index c4bba30c74..0000000000 --- a/operator/database/kinds/backups/bucket/adapt_test.go +++ /dev/null @@ -1,394 +0,0 @@ -package bucket - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func TestBucket_Secrets(t *testing.T) { - masterkey := "testMk" - features := []string{backup.Normal} - saJson := "testSA" - - bucketName := "testBucket2" - cron := "testCron2" - monitor := mntr.Monitor{} - namespace := "testNs2" - - dbURL := "testDB" - dbPort := int32(80) - kindVersion := "v0" - kind := "BucketBackup" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", kindVersion), "testComponent") - - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/"+kind, kindVersion, false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - allSecrets := map[string]string{ - "serviceaccountjson": saJson, - } - - _, _, _, secrets, existing, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - assert.NoError(t, err) - for key, value := range allSecrets { - assert.Contains(t, secrets, key) - assert.Contains(t, existing, key) - assert.Equal(t, value, secrets[key].Value) - } -} - -func TestBucket_AdaptBackup(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{backup.Normal} - saJson := "testSA" - - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - monitor := mntr.Monitor{} - namespace := "testNs2" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetBackup(client, namespace, k8sLabels, saJson) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestBucket_AdaptInstantBackup(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{backup.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - dbURL := "testDB" - dbPort := int32(80) - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - saJson := "testSA" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetInstantBackup(client, namespace, backupName, k8sLabels, saJson) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBucket_AdaptRestore(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{restore.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - saJson := "testSA" - dbURL := "testDB" - dbPort := int32(80) - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetRestore(client, namespace, backupName, k8sLabels, saJson) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -/* -func TestBucket_AdaptClean(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{clean.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - saJson := "testSA" - dbURL := "testDB" - dbPort := int32(80) - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetClean(client, namespace, backupName, k8sLabels, saJson) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - users := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, users) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -}*/ diff --git a/operator/database/kinds/backups/bucket/backup/adapt.go b/operator/database/kinds/backups/bucket/backup/adapt.go deleted file mode 100644 index e91d34e0fd..0000000000 --- a/operator/database/kinds/backups/bucket/backup/adapt.go +++ /dev/null @@ -1,140 +0,0 @@ -package backup - -import ( - "time" - - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/cronjob" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - corev1 "k8s.io/api/core/v1" -) - -const ( - defaultMode int32 = 256 - certPath = "/cockroach/cockroach-certs" - secretPath = "/secrets/sa.json" - backupPath = "/cockroach" - backupNameEnv = "BACKUP_NAME" - saJsonBase64Env = "SAJSON" - cronJobNamePrefix = "backup-" - internalSecretName = "client-certs" - rootSecretName = "cockroachdb.client.root" - timeout = 45 * time.Minute - Normal = "backup" - Instant = "instantbackup" -) - -func AdaptFunc( - monitor mntr.Monitor, - backupName string, - namespace string, - componentLabels *labels.Component, - checkDBReady operator.EnsureFunc, - bucketName string, - cron string, - secretName string, - secretKey string, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - dbURL string, - dbPort int32, - features []string, - image string, -) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - err error, -) { - - command := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - - jobSpecDef := getJobSpecDef( - nodeselector, - tolerations, - secretName, - secretKey, - backupName, - command, - image, - ) - - destroyers := []operator.DestroyFunc{} - queriers := []operator.QueryFunc{} - - cronJobDef := getCronJob( - namespace, - labels.MustForName(componentLabels, GetJobName(backupName)), - cron, - jobSpecDef, - ) - - destroyCJ, err := cronjob.AdaptFuncToDestroy(cronJobDef.Namespace, cronJobDef.Name) - if err != nil { - return nil, nil, err - } - - queryCJ, err := cronjob.AdaptFuncToEnsure(cronJobDef) - if err != nil { - return nil, nil, err - } - - jobDef := getJob( - namespace, - labels.MustForName(componentLabels, cronJobNamePrefix+backupName), - jobSpecDef, - ) - - destroyJ, err := job.AdaptFuncToDestroy(jobDef.Namespace, jobDef.Name) - if err != nil { - return nil, nil, err - } - - queryJ, err := job.AdaptFuncToEnsure(jobDef) - if err != nil { - return nil, nil, err - } - - for _, feature := range features { - switch feature { - case Normal: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyCJ), - ) - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryCJ), - ) - case Instant: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyJ), - ) - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryJ), - ) - } - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - nil -} - -func GetJobName(backupName string) string { - return cronJobNamePrefix + backupName -} diff --git a/operator/database/kinds/backups/bucket/backup/adapt_test.go b/operator/database/kinds/backups/bucket/backup/adapt_test.go deleted file mode 100644 index f4c7334b5d..0000000000 --- a/operator/database/kinds/backups/bucket/backup/adapt_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package backup - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestBackup_AdaptInstantBackup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Instant} - monitor := mntr.Monitor{} - namespace := "testNs" - - bucketName := "testBucket" - cron := "testCron" - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - image := "testImage" - secretKey := "testKey" - secretName := "testSecretName" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - getJobSpecDef( - nodeselector, - tolerations, - secretName, - secretKey, - backupName, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptInstantBackup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Instant} - monitor := mntr.Monitor{} - namespace := "testNs2" - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - image := "testImage2" - secretKey := "testKey2" - secretName := "testSecretName2" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - getJobSpecDef( - nodeselector, - tolerations, - secretName, - secretKey, - backupName, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptBackup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Normal} - monitor := mntr.Monitor{} - namespace := "testNs" - bucketName := "testBucket" - cron := "testCron" - timestamp := "test" - dbURL := "testDB" - dbPort := int32(80) - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - image := "testImage" - secretKey := "testKey" - secretName := "testSecretName" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getCronJob( - namespace, - nameLabels, - cron, - getJobSpecDef( - nodeselector, - tolerations, - secretName, - secretKey, - backupName, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ), - ) - - client.EXPECT().ApplyCronJob(jobDef).Times(1).Return(nil) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptBackup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Normal} - monitor := mntr.Monitor{} - namespace := "testNs2" - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - image := "testImage2" - secretKey := "testKey2" - secretName := "testSecretName2" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getCronJob( - namespace, - nameLabels, - cron, - getJobSpecDef( - nodeselector, - tolerations, - secretName, - secretKey, - backupName, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ), - ) - - client.EXPECT().ApplyCronJob(jobDef).Times(1).Return(nil) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - secretName, - secretKey, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} diff --git a/operator/database/kinds/backups/bucket/backup/cleanup.go b/operator/database/kinds/backups/bucket/backup/cleanup.go deleted file mode 100644 index 33fc5122b3..0000000000 --- a/operator/database/kinds/backups/bucket/backup/cleanup.go +++ /dev/null @@ -1,29 +0,0 @@ -package backup - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - - "github.com/caos/zitadel/operator" -) - -func GetCleanupFunc( - monitor mntr.Monitor, - namespace string, - backupName string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for backup to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil { - return fmt.Errorf("error while waiting for backup to be completed: %w", err) - } - monitor.Info("backup is completed, cleanup") - if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil { - return fmt.Errorf("error while trying to cleanup backup: %w", err) - } - monitor.Info("cleanup backup is completed") - return nil - } -} diff --git a/operator/database/kinds/backups/bucket/backup/cleanup_test.go b/operator/database/kinds/backups/bucket/backup/cleanup_test.go deleted file mode 100644 index cce11dd064..0000000000 --- a/operator/database/kinds/backups/bucket/backup/cleanup_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package backup - -import ( - "errors" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" -) - -func TestBackup_Cleanup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test" - namespace := "testNs" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} - -func TestBackup_Cleanup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test2" - namespace := "testNs2" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} diff --git a/operator/database/kinds/backups/bucket/backup/command.go b/operator/database/kinds/backups/bucket/backup/command.go deleted file mode 100644 index 3db5039bc5..0000000000 --- a/operator/database/kinds/backups/bucket/backup/command.go +++ /dev/null @@ -1,41 +0,0 @@ -package backup - -import ( - "strconv" - "strings" -) - -func getBackupCommand( - timestamp string, - bucketName string, - backupName string, - certsFolder string, - serviceAccountPath string, - dbURL string, - dbPort int32, -) string { - - backupCommands := make([]string, 0) - if timestamp != "" { - backupCommands = append(backupCommands, "export "+backupNameEnv+"="+timestamp) - } else { - backupCommands = append(backupCommands, "export "+backupNameEnv+"=$(date +%Y-%m-%dT%H:%M:%SZ)") - } - - backupCommands = append(backupCommands, "export "+saJsonBase64Env+"=$(cat "+serviceAccountPath+" | base64 | tr -d '\n' )") - - backupCommands = append(backupCommands, - strings.Join([]string{ - "cockroach", - "sql", - "--certs-dir=" + certsFolder, - "--host=" + dbURL, - "--port=" + strconv.Itoa(int(dbPort)), - "-e", - "\"BACKUP TO \\\"gs://" + bucketName + "/" + backupName + "/${" + backupNameEnv + "}?AUTH=specified&CREDENTIALS=${" + saJsonBase64Env + "}\\\";\"", - }, " ", - ), - ) - - return strings.Join(backupCommands, " && ") -} diff --git a/operator/database/kinds/backups/bucket/backup/command_test.go b/operator/database/kinds/backups/bucket/backup/command_test.go deleted file mode 100644 index 7b476b4fd4..0000000000 --- a/operator/database/kinds/backups/bucket/backup/command_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package backup - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Command1(t *testing.T) { - timestamp := "" - bucketName := "test" - backupName := "test" - dbURL := "testDB" - dbPort := int32(80) - - cmd := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - equals := "export " + backupNameEnv + "=$(date +%Y-%m-%dT%H:%M:%SZ) && export SAJSON=$(cat /secrets/sa.json | base64 | tr -d '\n' ) && cockroach sql --certs-dir=/cockroach/cockroach-certs --host=testDB --port=80 -e \"BACKUP TO \\\"gs://test/test/${BACKUP_NAME}?AUTH=specified&CREDENTIALS=${SAJSON}\\\";\"" - assert.Equal(t, equals, cmd) -} - -func TestBackup_Command2(t *testing.T) { - timestamp := "test" - bucketName := "test" - backupName := "test" - dbURL := "testDB" - dbPort := int32(80) - - cmd := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - equals := "export " + backupNameEnv + "=test && export SAJSON=$(cat /secrets/sa.json | base64 | tr -d '\n' ) && cockroach sql --certs-dir=/cockroach/cockroach-certs --host=testDB --port=80 -e \"BACKUP TO \\\"gs://test/test/${BACKUP_NAME}?AUTH=specified&CREDENTIALS=${SAJSON}\\\";\"" - assert.Equal(t, equals, cmd) -} diff --git a/operator/database/kinds/backups/bucket/backup/job.go b/operator/database/kinds/backups/bucket/backup/job.go deleted file mode 100644 index 8a064a30aa..0000000000 --- a/operator/database/kinds/backups/bucket/backup/job.go +++ /dev/null @@ -1,101 +0,0 @@ -package backup - -import ( - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - batchv1 "k8s.io/api/batch/v1" - "k8s.io/api/batch/v1beta1" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func getCronJob( - namespace string, - nameLabels *labels.Name, - cron string, - jobSpecDef batchv1.JobSpec, -) *v1beta1.CronJob { - return &v1beta1.CronJob{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: v1beta1.CronJobSpec{ - Schedule: cron, - ConcurrencyPolicy: v1beta1.ForbidConcurrent, - JobTemplate: v1beta1.JobTemplateSpec{ - Spec: jobSpecDef, - }, - }, - } -} - -func getJob( - namespace string, - nameLabels *labels.Name, - jobSpecDef batchv1.JobSpec, -) *batchv1.Job { - return &batchv1.Job{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: jobSpecDef, - } -} - -func getJobSpecDef( - nodeselector map[string]string, - tolerations []corev1.Toleration, - secretName string, - secretKey string, - backupName string, - command string, - image string, -) batchv1.JobSpec { - return batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - } -} diff --git a/operator/database/kinds/backups/bucket/backup/job_test.go b/operator/database/kinds/backups/bucket/backup/job_test.go deleted file mode 100644 index e54aeb5bb8..0000000000 --- a/operator/database/kinds/backups/bucket/backup/job_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package backup - -import ( - "testing" - - "github.com/caos/zitadel/operator/helpers" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" -) - -func TestBackup_JobSpec1(t *testing.T) { - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - command := "test" - secretKey := "testKey" - secretName := "testSecretName" - image := "testImage" - - equals := batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - } - - assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, command, image)) -} - -func TestBackup_JobSpec2(t *testing.T) { - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - command := "test2" - secretKey := "testKey2" - secretName := "testSecretName2" - image := "testImage2" - - equals := batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - } - - assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, command, image)) -} diff --git a/operator/database/kinds/backups/bucket/desired.go b/operator/database/kinds/backups/bucket/desired.go deleted file mode 100644 index 04f7e1f228..0000000000 --- a/operator/database/kinds/backups/bucket/desired.go +++ /dev/null @@ -1,52 +0,0 @@ -package bucket - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec *Spec -} - -type Spec struct { - Verbose bool - Cron string `yaml:"cron,omitempty"` - Bucket string `yaml:"bucket,omitempty"` - ServiceAccountJSON *secret.Secret `yaml:"serviceAccountJSON,omitempty"` - ExistingServiceAccountJSON *secret.Existing `yaml:"existingServiceAccountJSON,omitempty"` -} - -func (s *Spec) IsZero() bool { - if ((s.ServiceAccountJSON == nil || s.ServiceAccountJSON.IsZero()) && (s.ExistingServiceAccountJSON == nil || s.ExistingServiceAccountJSON.IsZero())) && - !s.Verbose && - s.Cron == "" && - s.Bucket == "" { - return true - } - return false -} - -func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{ - Common: desiredTree.Common, - Spec: &Spec{}, - } - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err)) - } - - return desiredKind, nil -} - -func (d *DesiredV0) validateSecrets() error { - if err := secret.ValidateSecret(d.Spec.ServiceAccountJSON, d.Spec.ExistingServiceAccountJSON); err != nil { - return fmt.Errorf("validating api key failed: %w", err) - } - return nil -} diff --git a/operator/database/kinds/backups/bucket/desired_test.go b/operator/database/kinds/backups/bucket/desired_test.go deleted file mode 100644 index 26c477b637..0000000000 --- a/operator/database/kinds/backups/bucket/desired_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package bucket - -import ( - "testing" - - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" -) - -const ( - masterkey = "testMk" - cron = "testCron" - bucketName = "testBucket" - saJson = "testSa" - yamlFile = `kind: databases.caos.ch/BucketBackup -version: v0 -spec: - verbose: true - cron: testCron - bucket: testBucket - serviceAccountJSON: - encryption: AES256 - encoding: Base64 - value: luyAqtopzwLcaIhJj7KhWmbUsA7cQg== -` - - yamlFileWithoutSecret = `kind: databases.caos.ch/BucketBackup -version: v0 -spec: - verbose: true - cron: testCron - bucket: testBucket -` - yamlEmpty = `kind: databases.caos.ch/BucketBackup -version: v0` -) - -var ( - desired = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - Encryption: "AES256", - Encoding: "Base64", - }, - }, - } - desiredWithoutSecret = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - }, - } - desiredEmpty = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: false, - Cron: "", - Bucket: "", - ServiceAccountJSON: &secret.Secret{ - Value: "", - }, - }, - } - - desiredNil = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - } -) - -func marshalYaml(t *testing.T, masterkey string, struc *DesiredV0) []byte { - secret.Masterkey = masterkey - data, err := yaml.Marshal(struc) - assert.NoError(t, err) - return data -} - -func unmarshalYaml(t *testing.T, masterkey string, yamlFile []byte) *tree.Tree { - secret.Masterkey = masterkey - desiredTree := &tree.Tree{} - assert.NoError(t, yaml.Unmarshal(yamlFile, desiredTree)) - return desiredTree -} - -func getDesiredTree(t *testing.T, masterkey string, desired *DesiredV0) *tree.Tree { - return unmarshalYaml(t, masterkey, marshalYaml(t, masterkey, desired)) -} - -func TestBucket_DesiredParse(t *testing.T) { - - result := string(marshalYaml(t, masterkey, &desiredWithoutSecret)) - assert.Equal(t, yamlFileWithoutSecret, result) - - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlFile)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.Equal(t, &desired, desiredKind) -} - -func TestBucket_DesiredNotZero(t *testing.T) { - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlFile)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.False(t, desiredKind.Spec.IsZero()) -} - -func TestBucket_DesiredZero(t *testing.T) { - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlEmpty)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.True(t, desiredKind.Spec.IsZero()) -} diff --git a/operator/database/kinds/backups/bucket/list.go b/operator/database/kinds/backups/bucket/list.go deleted file mode 100644 index 32dbb1143e..0000000000 --- a/operator/database/kinds/backups/bucket/list.go +++ /dev/null @@ -1,76 +0,0 @@ -package bucket - -import ( - "context" - "fmt" - "strings" - - "cloud.google.com/go/storage" - "google.golang.org/api/iterator" - "google.golang.org/api/option" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/secret/read" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator/database/kinds/backups/core" -) - -func BackupList() core.BackupListFunc { - return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) { - desiredKind, err := ParseDesiredV0(desired) - if err != nil { - return nil, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - monitor.Verbose() - } - - value, err := read.GetSecretValue(k8sClient, desiredKind.Spec.ServiceAccountJSON, desiredKind.Spec.ExistingServiceAccountJSON) - if err != nil { - return nil, err - } - - return listFilesWithFilter(value, desiredKind.Spec.Bucket, name) - } -} - -func listFilesWithFilter(serviceAccountJSON string, bucketName, name string) ([]string, error) { - ctx := context.Background() - client, err := storage.NewClient(ctx, option.WithCredentialsJSON([]byte(serviceAccountJSON))) - - if err != nil { - return nil, err - } - bkt := client.Bucket(bucketName) - - names := make([]string, 0) - it := bkt.Objects(ctx, &storage.Query{Prefix: name + "/"}) - for { - attrs, err := it.Next() - if err == iterator.Done { - break - } - if err != nil { - return nil, err - } - parts := strings.Split(attrs.Name, "/") - found := false - for _, name := range names { - if len(parts) < 2 { - continue - } - if name == parts[1] { - found = true - } - } - if !found { - names = append(names, parts[1]) - } - } - - return names, nil -} diff --git a/operator/database/kinds/backups/bucket/mock.go b/operator/database/kinds/backups/bucket/mock.go deleted file mode 100644 index 4009d98951..0000000000 --- a/operator/database/kinds/backups/bucket/mock.go +++ /dev/null @@ -1,84 +0,0 @@ -package bucket - -import ( - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - "github.com/golang/mock/gomock" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func SetQueriedForDatabases(databases, users []string) map[string]interface{} { - queried := map[string]interface{}{} - core.SetQueriedForDatabaseDBList(queried, databases, users) - - return queried -} - -func SetInstantBackup( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - backupName string, - labels map[string]string, - saJson string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: namespace, - Labels: labels, - }, - StringData: map[string]string{secretKey: saJson}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplyJob(gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().GetJob(namespace, backup.GetJobName(backupName)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, backup.GetJobName(backupName))) - k8sClient.EXPECT().WaitUntilJobCompleted(namespace, backup.GetJobName(backupName), gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().DeleteJob(namespace, backup.GetJobName(backupName)).Times(1).Return(nil) -} - -func SetBackup( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - labels map[string]string, - saJson string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: namespace, - Labels: labels, - }, - StringData: map[string]string{secretKey: saJson}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - k8sClient.EXPECT().ApplyCronJob(gomock.Any()).Times(1).Return(nil) -} - -func SetRestore( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - backupName string, - labels map[string]string, - saJson string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: namespace, - Labels: labels, - }, - StringData: map[string]string{secretKey: saJson}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplyJob(gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().GetJob(namespace, restore.GetJobName(backupName)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, restore.GetJobName(backupName))) - k8sClient.EXPECT().WaitUntilJobCompleted(namespace, restore.GetJobName(backupName), gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().DeleteJob(namespace, restore.GetJobName(backupName)).Times(1).Return(nil) -} diff --git a/operator/database/kinds/backups/bucket/restore/adapt.go b/operator/database/kinds/backups/bucket/restore/adapt.go deleted file mode 100644 index 0675c6d13a..0000000000 --- a/operator/database/kinds/backups/bucket/restore/adapt.go +++ /dev/null @@ -1,100 +0,0 @@ -package restore - -import ( - "time" - - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - corev1 "k8s.io/api/core/v1" -) - -const ( - Instant = "restore" - defaultMode = int32(256) - certPath = "/cockroach/cockroach-certs" - secretPath = "/secrets/sa.json" - jobPrefix = "backup-" - jobSuffix = "-restore" - internalSecretName = "client-certs" - rootSecretName = "cockroachdb.client.root" - timeout = 45 * time.Minute - saJsonBase64Env = "SAJSON" -) - -func AdaptFunc( - monitor mntr.Monitor, - backupName string, - namespace string, - componentLabels *labels.Component, - bucketName string, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - checkDBReady operator.EnsureFunc, - secretName string, - secretKey string, - dbURL string, - dbPort int32, - image string, -) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - err error, -) { - - jobName := jobPrefix + backupName + jobSuffix - command := getCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - - jobdef := getJob( - namespace, - labels.MustForName(componentLabels, GetJobName(backupName)), - nodeselector, - tolerations, - secretName, - secretKey, - command, - image, - ) - - destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyJ), - } - - queryJ, err := job.AdaptFuncToEnsure(jobdef) - if err != nil { - return nil, nil, err - } - - queriers := []operator.QueryFunc{ - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryJ), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - - nil -} - -func GetJobName(backupName string) string { - return jobPrefix + backupName + jobSuffix -} diff --git a/operator/database/kinds/backups/bucket/restore/adapt_test.go b/operator/database/kinds/backups/bucket/restore/adapt_test.go deleted file mode 100644 index 2e5c904653..0000000000 --- a/operator/database/kinds/backups/bucket/restore/adapt_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package restore - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestBackup_Adapt1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - monitor := mntr.Monitor{} - namespace := "testNs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - timestamp := "testTs" - backupName := "testName2" - bucketName := "testBucket2" - image := "testImage2" - secretKey := "testKey" - secretName := "testSecretName" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "testVersion"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - secretName, - secretKey, - getCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - bucketName, - timestamp, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - dbURL, - dbPort, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_Adapt2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - monitor := mntr.Monitor{} - namespace := "testNs2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - timestamp := "testTs" - backupName := "testName2" - bucketName := "testBucket2" - image := "testImage2" - secretKey := "testKey2" - secretName := "testSecretName2" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent2") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - secretName, - secretKey, - getCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ), - image, - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - bucketName, - timestamp, - nodeselector, - tolerations, - checkDBReady, - secretName, - secretKey, - dbURL, - dbPort, - image, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} diff --git a/operator/database/kinds/backups/bucket/restore/cleanup.go b/operator/database/kinds/backups/bucket/restore/cleanup.go deleted file mode 100644 index afd8ddaeda..0000000000 --- a/operator/database/kinds/backups/bucket/restore/cleanup.go +++ /dev/null @@ -1,28 +0,0 @@ -package restore - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" -) - -func GetCleanupFunc( - monitor mntr.Monitor, - namespace, - backupName string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for restore to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil { - return fmt.Errorf("error while waiting for restore to be completed: %w", err) - } - monitor.Info("restore is completed, cleanup") - if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil { - return fmt.Errorf("error while trying to cleanup restore: %w", err) - } - monitor.Info("restore cleanup is completed") - return nil - } -} diff --git a/operator/database/kinds/backups/bucket/restore/cleanup_test.go b/operator/database/kinds/backups/bucket/restore/cleanup_test.go deleted file mode 100644 index 81671b1f30..0000000000 --- a/operator/database/kinds/backups/bucket/restore/cleanup_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package restore - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Cleanup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test" - namespace := "testNs" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} - -func TestBackup_Cleanup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test2" - namespace := "testNs2" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} diff --git a/operator/database/kinds/backups/bucket/restore/command.go b/operator/database/kinds/backups/bucket/restore/command.go deleted file mode 100644 index eb08907900..0000000000 --- a/operator/database/kinds/backups/bucket/restore/command.go +++ /dev/null @@ -1,36 +0,0 @@ -package restore - -import ( - "strconv" - "strings" -) - -func getCommand( - timestamp string, - bucketName string, - backupName string, - certsFolder string, - serviceAccountPath string, - dbURL string, - dbPort int32, -) string { - - backupCommands := make([]string, 0) - - backupCommands = append(backupCommands, "export "+saJsonBase64Env+"=$(cat "+serviceAccountPath+" | base64 | tr -d '\n' )") - - backupCommands = append(backupCommands, - strings.Join([]string{ - "cockroach", - "sql", - "--certs-dir=" + certsFolder, - "--host=" + dbURL, - "--port=" + strconv.Itoa(int(dbPort)), - "-e", - "\"RESTORE FROM \\\"gs://" + bucketName + "/" + backupName + "/" + timestamp + "?AUTH=specified&CREDENTIALS=${" + saJsonBase64Env + "}\\\";\"", - }, " ", - ), - ) - - return strings.Join(backupCommands, " && ") -} diff --git a/operator/database/kinds/backups/bucket/restore/command_test.go b/operator/database/kinds/backups/bucket/restore/command_test.go deleted file mode 100644 index 3f8464664c..0000000000 --- a/operator/database/kinds/backups/bucket/restore/command_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package restore - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Command1(t *testing.T) { - timestamp := "test1" - bucketName := "testBucket" - backupName := "testBackup" - dbURL := "testDB" - dbPort := int32(80) - - cmd := getCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - - equals := "export SAJSON=$(cat /secrets/sa.json | base64 | tr -d '\n' ) && cockroach sql --certs-dir=/cockroach/cockroach-certs --host=testDB --port=80 -e \"RESTORE FROM \\\"gs://testBucket/testBackup/test1?AUTH=specified&CREDENTIALS=${SAJSON}\\\";\"" - assert.Equal(t, equals, cmd) -} - -func TestBackup_Command2(t *testing.T) { - timestamp := "test2" - bucketName := "testBucket" - backupName := "testBackup" - dbURL := "testDB2" - dbPort := int32(81) - - cmd := getCommand( - timestamp, - bucketName, - backupName, - certPath, - secretPath, - dbURL, - dbPort, - ) - equals := "export SAJSON=$(cat /secrets/sa.json | base64 | tr -d '\n' ) && cockroach sql --certs-dir=/cockroach/cockroach-certs --host=testDB2 --port=81 -e \"RESTORE FROM \\\"gs://testBucket/testBackup/test2?AUTH=specified&CREDENTIALS=${SAJSON}\\\";\"" - assert.Equal(t, equals, cmd) -} diff --git a/operator/database/kinds/backups/bucket/restore/job.go b/operator/database/kinds/backups/bucket/restore/job.go deleted file mode 100644 index fc06477949..0000000000 --- a/operator/database/kinds/backups/bucket/restore/job.go +++ /dev/null @@ -1,71 +0,0 @@ -package restore - -import ( - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func getJob( - namespace string, - nameLabels *labels.Name, - nodeselector map[string]string, - tolerations []corev1.Toleration, - secretName string, - secretKey string, - command string, - image string, -) *batchv1.Job { - return &batchv1.Job{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - RestartPolicy: corev1.RestartPolicyNever, - Containers: []corev1.Container{{ - Name: nameLabels.Name(), - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - }, - } -} diff --git a/operator/database/kinds/backups/bucket/restore/job_test.go b/operator/database/kinds/backups/bucket/restore/job_test.go deleted file mode 100644 index dbd95d6111..0000000000 --- a/operator/database/kinds/backups/bucket/restore/job_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package restore - -import ( - "testing" - - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestBackup_Job1(t *testing.T) { - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - command := "test" - secretKey := "testKey" - secretName := "testSecretName" - jobName := "testJob" - namespace := "testNs" - image := "testImage" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": jobName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testOpVersion", - "caos.ch/apiversion": "testVersion", - "caos.ch/kind": "testKind"} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testOpVersion"), "testKind", "testVersion"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - equals := - &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: jobName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - }, - } - - assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, image)) -} - -func TestBackup_Job2(t *testing.T) { - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - command := "test2" - secretKey := "testKey2" - secretName := "testSecretName2" - jobName := "testJob2" - namespace := "testNs2" - testImage := "testImage2" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": jobName, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testOpVersion2", - "caos.ch/apiversion": "testVersion2", - "caos.ch/kind": "testKind2"} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testOpVersion2"), "testKind2", "testVersion2"), "testComponent2") - nameLabels := labels.MustForName(componentLabels, jobName) - - equals := - &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: jobName, - Image: testImage, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: secretKey, - SubPath: secretKey, - MountPath: secretPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: secretKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - }, - }, - }}, - }, - }, - }, - } - - assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, testImage)) -} diff --git a/operator/database/kinds/backups/bucket/secrets.go b/operator/database/kinds/backups/bucket/secrets.go deleted file mode 100644 index 17eca944c8..0000000000 --- a/operator/database/kinds/backups/bucket/secrets.go +++ /dev/null @@ -1,30 +0,0 @@ -package bucket - -import ( - "github.com/caos/orbos/pkg/secret" -) - -func getSecretsMap(desiredKind *DesiredV0) (map[string]*secret.Secret, map[string]*secret.Existing) { - - var ( - secrets = make(map[string]*secret.Secret, 0) - existing = make(map[string]*secret.Existing, 0) - ) - if desiredKind.Spec == nil { - desiredKind.Spec = &Spec{} - } - - if desiredKind.Spec.ServiceAccountJSON == nil { - desiredKind.Spec.ServiceAccountJSON = &secret.Secret{} - } - - if desiredKind.Spec.ExistingServiceAccountJSON == nil { - desiredKind.Spec.ExistingServiceAccountJSON = &secret.Existing{} - } - - sakey := "serviceaccountjson" - secrets[sakey] = desiredKind.Spec.ServiceAccountJSON - existing[sakey] = desiredKind.Spec.ExistingServiceAccountJSON - - return secrets, existing -} diff --git a/operator/database/kinds/backups/bucket/secrets_test.go b/operator/database/kinds/backups/bucket/secrets_test.go deleted file mode 100644 index 4b4810b394..0000000000 --- a/operator/database/kinds/backups/bucket/secrets_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package bucket - -import ( - "testing" - - "github.com/caos/orbos/pkg/secret" - "github.com/stretchr/testify/assert" -) - -func TestBucket_getSecretsFull(t *testing.T) { - secrets, existing := getSecretsMap(&desired) - assert.Equal(t, desired.Spec.ServiceAccountJSON, secrets["serviceaccountjson"]) - assert.Equal(t, desired.Spec.ExistingServiceAccountJSON, existing["serviceaccountjson"]) -} - -func TestBucket_getSecretsEmpty(t *testing.T) { - secrets, existing := getSecretsMap(&desiredWithoutSecret) - assert.Equal(t, &secret.Secret{}, secrets["serviceaccountjson"]) - assert.Equal(t, &secret.Existing{}, existing["serviceaccountjson"]) -} - -func TestBucket_getSecretsNil(t *testing.T) { - secrets, existing := getSecretsMap(&desiredNil) - assert.Equal(t, &secret.Secret{}, secrets["serviceaccountjson"]) - assert.Equal(t, &secret.Existing{}, existing["serviceaccountjson"]) -} diff --git a/operator/database/kinds/backups/core/list.go b/operator/database/kinds/backups/core/list.go deleted file mode 100644 index 4667ddcbe8..0000000000 --- a/operator/database/kinds/backups/core/list.go +++ /dev/null @@ -1,9 +0,0 @@ -package core - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" -) - -type BackupListFunc func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) diff --git a/operator/database/kinds/backups/s3/adapt.go b/operator/database/kinds/backups/s3/adapt.go deleted file mode 100644 index c03289fa95..0000000000 --- a/operator/database/kinds/backups/s3/adapt.go +++ /dev/null @@ -1,296 +0,0 @@ -package s3 - -import ( - "fmt" - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/secret" - "github.com/caos/orbos/pkg/labels" - secretpkg "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/secret/read" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/common" - "github.com/caos/zitadel/operator/database/kinds/backups/s3/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/s3/restore" - corev1 "k8s.io/api/core/v1" -) - -const ( - accessKeyIDName = "backup-accessaccountkey" - accessKeyIDKey = "accessaccountkey" - secretAccessKeyName = "backup-secretaccesskey" - secretAccessKeyKey = "secretaccesskey" - sessionTokenName = "backup-sessiontoken" - sessionTokenKey = "sessiontoken" -) - -func AdaptFunc( - name string, - namespace string, - componentLabels *labels.Component, - checkDBReady operator.EnsureFunc, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - version string, - dbURL string, - dbPort int32, - features []string, - customImageRegistry string, -) operator.AdaptFunc { - return func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, - ) ( - operator.QueryFunc, - operator.DestroyFunc, - operator.ConfigureFunc, - map[string]*secretpkg.Secret, - map[string]*secretpkg.Existing, - bool, - error, - ) { - - internalMonitor := monitor.WithField("component", "backup") - - desiredKind, err := ParseDesiredV0(desired) - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %s", err) - } - desired.Parsed = desiredKind - - secrets, existing := getSecretsMap(desiredKind) - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - internalMonitor.Verbose() - } - - destroySAKI, err := secret.AdaptFuncToDestroy(namespace, accessKeyIDName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - destroySSAK, err := secret.AdaptFuncToDestroy(namespace, secretAccessKeyName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - destroySSTK, err := secret.AdaptFuncToDestroy(namespace, sessionTokenName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - image := common.BackupImage.Reference(customImageRegistry, version) - - _, destroyB, err := backup.AdaptFunc( - internalMonitor, - name, - namespace, - componentLabels, - checkDBReady, - desiredKind.Spec.Bucket, - desiredKind.Spec.Cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - desiredKind.Spec.Region, - desiredKind.Spec.Endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - _, destroyR, err := restore.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - desiredKind.Spec.Bucket, - timestamp, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - desiredKind.Spec.Region, - desiredKind.Spec.Endpoint, - nodeselector, - tolerations, - checkDBReady, - dbURL, - dbPort, - image, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - destroyers := make([]operator.DestroyFunc, 0) - for _, feature := range features { - switch feature { - case backup.Normal, backup.Instant: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroySSAK), - operator.ResourceDestroyToZitadelDestroy(destroySAKI), - operator.ResourceDestroyToZitadelDestroy(destroySSTK), - destroyB, - ) - case restore.Instant: - destroyers = append(destroyers, - destroyR, - ) - } - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - - if err := desiredKind.validateSecrets(); err != nil { - return nil, err - } - - valueAKI, err := read.GetSecretValue(k8sClient, desiredKind.Spec.AccessKeyID, desiredKind.Spec.ExistingAccessKeyID) - if err != nil { - return nil, err - } - - querySAKI, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, accessKeyIDName), map[string]string{accessKeyIDKey: valueAKI}) - if err != nil { - return nil, err - } - - valueSAK, err := read.GetSecretValue(k8sClient, desiredKind.Spec.SecretAccessKey, desiredKind.Spec.ExistingSecretAccessKey) - if err != nil { - return nil, err - } - - querySSAK, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, secretAccessKeyName), map[string]string{secretAccessKeyKey: valueSAK}) - if err != nil { - return nil, err - } - - valueST, err := read.GetSecretValue(k8sClient, desiredKind.Spec.SessionToken, desiredKind.Spec.ExistingSessionToken) - if err != nil { - return nil, err - } - - querySST, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, sessionTokenName), map[string]string{sessionTokenKey: valueST}) - if err != nil { - return nil, err - } - - queryB, _, err := backup.AdaptFunc( - internalMonitor, - name, - namespace, - componentLabels, - checkDBReady, - desiredKind.Spec.Bucket, - desiredKind.Spec.Cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - desiredKind.Spec.Region, - desiredKind.Spec.Endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - image, - ) - if err != nil { - return nil, err - } - - queryR, _, err := restore.AdaptFunc( - monitor, - name, - namespace, - componentLabels, - desiredKind.Spec.Bucket, - timestamp, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - desiredKind.Spec.Region, - desiredKind.Spec.Endpoint, - nodeselector, - tolerations, - checkDBReady, - dbURL, - dbPort, - image, - ) - if err != nil { - return nil, err - } - - queriers := make([]operator.QueryFunc, 0) - cleanupQueries := make([]operator.QueryFunc, 0) - for _, feature := range features { - switch feature { - case backup.Normal: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(querySAKI), - operator.ResourceQueryToZitadelQuery(querySSAK), - operator.ResourceQueryToZitadelQuery(querySST), - queryB, - ) - case backup.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(querySAKI), - operator.ResourceQueryToZitadelQuery(querySSAK), - operator.ResourceQueryToZitadelQuery(querySST), - queryB, - ) - cleanupQueries = append(cleanupQueries, - operator.EnsureFuncToQueryFunc(backup.GetCleanupFunc(monitor, namespace, name)), - ) - case restore.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(querySAKI), - operator.ResourceQueryToZitadelQuery(querySSAK), - operator.ResourceQueryToZitadelQuery(querySST), - queryR, - ) - cleanupQueries = append(cleanupQueries, - operator.EnsureFuncToQueryFunc(restore.GetCleanupFunc(monitor, namespace, name)), - ) - } - - } - - for _, cleanup := range cleanupQueries { - queriers = append(queriers, cleanup) - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - func(kubernetes.ClientInt, map[string]interface{}, bool) error { return nil }, - secrets, - existing, - false, - nil - } -} diff --git a/operator/database/kinds/backups/s3/adapt_test.go b/operator/database/kinds/backups/s3/adapt_test.go deleted file mode 100644 index 7fcaabefbd..0000000000 --- a/operator/database/kinds/backups/s3/adapt_test.go +++ /dev/null @@ -1,500 +0,0 @@ -package s3 - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func TestBucket_Secrets(t *testing.T) { - masterkey := "testMk" - features := []string{backup.Normal} - region := "testRegion" - endpoint := "testEndpoint" - akid := "testAKID" - sak := "testSAK" - st := "testST" - - bucketName := "testBucket2" - cron := "testCron2" - monitor := mntr.Monitor{} - namespace := "testNs2" - - dbURL := "testDB" - dbPort := int32(80) - kindVersion := "v0" - kind := "BucketBackup" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", kindVersion), "testComponent") - - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/"+kind, kindVersion, false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Endpoint: endpoint, - Region: region, - AccessKeyID: &secret.Secret{ - Value: akid, - }, - SecretAccessKey: &secret.Secret{ - Value: sak, - }, - SessionToken: &secret.Secret{ - Value: st, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - allSecrets := map[string]string{ - "accesskeyid": "testAKID", - "secretaccesskey": "testSAK", - "sessiontoken": "testST", - } - - _, _, _, secrets, existing, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - assert.NoError(t, err) - for key, value := range allSecrets { - assert.Contains(t, secrets, key) - assert.Contains(t, existing, key) - assert.Equal(t, value, secrets[key].Value) - } -} - -func TestBucket_AdaptBackup(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{backup.Normal} - region := "testRegion" - endpoint := "testEndpoint" - akid := "testAKID" - sak := "testSAK" - st := "testST" - - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - monitor := mntr.Monitor{} - namespace := "testNs2" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabelsAKID := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": accessKeyIDName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsSAK := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": secretAccessKeyName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsST := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": sessionTokenName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Endpoint: endpoint, - Region: region, - AccessKeyID: &secret.Secret{ - Value: akid, - }, - SecretAccessKey: &secret.Secret{ - Value: sak, - }, - SessionToken: &secret.Secret{ - Value: st, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetBackup(client, namespace, k8sLabelsAKID, k8sLabelsSAK, k8sLabelsST, akid, sak, st) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestBucket_AdaptInstantBackup(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{backup.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - dbURL := "testDB" - dbPort := int32(80) - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabelsAKID := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": accessKeyIDName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsSAK := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": secretAccessKeyName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsST := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": sessionTokenName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - region := "testRegion" - endpoint := "testEndpoint" - akid := "testAKID" - sak := "testSAK" - st := "testST" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Endpoint: endpoint, - Region: region, - AccessKeyID: &secret.Secret{ - Value: akid, - }, - SecretAccessKey: &secret.Secret{ - Value: sak, - }, - SessionToken: &secret.Secret{ - Value: st, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetInstantBackup(client, namespace, backupName, k8sLabelsAKID, k8sLabelsSAK, k8sLabelsST, akid, sak, st) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBucket_AdaptRestore(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{restore.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabelsAKID := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": accessKeyIDName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsSAK := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": secretAccessKeyName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - k8sLabelsST := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": sessionTokenName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - region := "testRegion" - endpoint := "testEndpoint" - akid := "testAKID" - sak := "testSAK" - st := "testST" - dbURL := "testDB" - dbPort := int32(80) - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Endpoint: endpoint, - Region: region, - AccessKeyID: &secret.Secret{ - Value: akid, - }, - SecretAccessKey: &secret.Secret{ - Value: sak, - }, - SessionToken: &secret.Secret{ - Value: st, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetRestore(client, namespace, backupName, k8sLabelsAKID, k8sLabelsSAK, k8sLabelsST, akid, sak, st) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - "", - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, []string{}) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -/* -func TestBucket_AdaptClean(t *testing.T) { - masterkey := "testMk" - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - features := []string{clean.Instant} - - bucketName := "testBucket1" - cron := "testCron" - monitor := mntr.Monitor{} - namespace := "testNs" - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "BucketBackup", "v0"), "testComponent") - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - saJson := "testSA" - dbURL := "testDB" - dbPort := int32(80) - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: &tree.Common{ - Kind: "databases.caos.ch/BucketBackup", - Version: "v0", - }, - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - SetClean(client, namespace, backupName, k8sLabels, saJson) - - query, _, _, _, _, _, err := AdaptFunc( - backupName, - namespace, - componentLabels, - checkDBReady, - timestamp, - nodeselector, - tolerations, - version, - dbURL, - dbPort, - features, - )( - monitor, - desired, - &tree.Tree{}, - ) - - assert.NoError(t, err) - databases := []string{"test1", "test2"} - users := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases, users) - ensure, err := query(client, queried) - assert.NotNil(t, ensure) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -}*/ diff --git a/operator/database/kinds/backups/s3/backup/adapt.go b/operator/database/kinds/backups/s3/backup/adapt.go deleted file mode 100644 index a04a4ca4d8..0000000000 --- a/operator/database/kinds/backups/s3/backup/adapt.go +++ /dev/null @@ -1,154 +0,0 @@ -package backup - -import ( - "time" - - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/cronjob" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - corev1 "k8s.io/api/core/v1" -) - -const ( - defaultMode int32 = 256 - certPath = "/cockroach/cockroach-certs" - accessKeyIDPath = "/secrets/accessaccountkey" - secretAccessKeyPath = "/secrets/secretaccesskey" - sessionTokenPath = "/secrets/sessiontoken" - backupNameEnv = "BACKUP_NAME" - cronJobNamePrefix = "backup-" - internalSecretName = "client-certs" - rootSecretName = "cockroachdb.client.root" - timeout = 15 * time.Minute - Normal = "backup" - Instant = "instantbackup" -) - -func AdaptFunc( - monitor mntr.Monitor, - backupName string, - namespace string, - componentLabels *labels.Component, - checkDBReady operator.EnsureFunc, - bucketName string, - cron string, - accessKeyIDName string, - accessKeyIDKey string, - secretAccessKeyName string, - secretAccessKeyKey string, - sessionTokenName string, - sessionTokenKey string, - region string, - endpoint string, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - dbURL string, - dbPort int32, - features []string, - image string, -) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - err error, -) { - - command := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - - jobSpecDef := getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - image, - command, - ) - - destroyers := []operator.DestroyFunc{} - queriers := []operator.QueryFunc{} - - cronJobDef := getCronJob( - namespace, - labels.MustForName(componentLabels, GetJobName(backupName)), - cron, - jobSpecDef, - ) - - destroyCJ, err := cronjob.AdaptFuncToDestroy(cronJobDef.Namespace, cronJobDef.Name) - if err != nil { - return nil, nil, err - } - - queryCJ, err := cronjob.AdaptFuncToEnsure(cronJobDef) - if err != nil { - return nil, nil, err - } - - jobDef := getJob( - namespace, - labels.MustForName(componentLabels, cronJobNamePrefix+backupName), - jobSpecDef, - ) - - destroyJ, err := job.AdaptFuncToDestroy(jobDef.Namespace, jobDef.Name) - if err != nil { - return nil, nil, err - } - - queryJ, err := job.AdaptFuncToEnsure(jobDef) - if err != nil { - return nil, nil, err - } - - for _, feature := range features { - switch feature { - case Normal: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyCJ), - ) - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryCJ), - ) - case Instant: - destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyJ), - ) - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryJ), - ) - } - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - nil -} - -func GetJobName(backupName string) string { - return cronJobNamePrefix + backupName -} diff --git a/operator/database/kinds/backups/s3/backup/adapt_test.go b/operator/database/kinds/backups/s3/backup/adapt_test.go deleted file mode 100644 index aa3a259fc8..0000000000 --- a/operator/database/kinds/backups/s3/backup/adapt_test.go +++ /dev/null @@ -1,404 +0,0 @@ -package backup - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestBackup_AdaptInstantBackup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Instant} - monitor := mntr.Monitor{} - namespace := "testNs" - - bucketName := "testBucket" - cron := "testCron" - timestamp := "test" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - accessKeyIDName := "testAKIN" - accessKeyIDKey := "testAKIK" - secretAccessKeyName := "testSAKN" - secretAccessKeyKey := "testSAKK" - sessionTokenName := "testSTN" - sessionTokenKey := "testSTK" - region := "region" - endpoint := "endpoint" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - version, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - version, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptInstantBackup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Instant} - monitor := mntr.Monitor{} - namespace := "testNs2" - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - accessKeyIDName := "testAKIN2" - accessKeyIDKey := "testAKIK2" - secretAccessKeyName := "testSAKN2" - secretAccessKeyKey := "testSAKK2" - sessionTokenName := "testSTN2" - sessionTokenKey := "testSTK2" - region := "region2" - endpoint := "endpoint2" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - version, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - version, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptBackup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Normal} - monitor := mntr.Monitor{} - namespace := "testNs" - bucketName := "testBucket" - cron := "testCron" - timestamp := "test" - dbURL := "testDB" - dbPort := int32(80) - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - accessKeyIDName := "testAKIN" - accessKeyIDKey := "testAKIK" - secretAccessKeyName := "testSAKN" - secretAccessKeyKey := "testSAKK" - sessionTokenName := "testSTN" - sessionTokenKey := "testSTK" - region := "region" - endpoint := "endpoint" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getCronJob( - namespace, - nameLabels, - cron, - getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - version, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ), - ) - - client.EXPECT().ApplyCronJob(jobDef).Times(1).Return(nil) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - version, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_AdaptBackup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - features := []string{Normal} - monitor := mntr.Monitor{} - namespace := "testNs2" - dbURL := "testDB" - dbPort := int32(80) - bucketName := "testBucket2" - cron := "testCron2" - timestamp := "test2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - accessKeyIDName := "testAKIN2" - accessKeyIDKey := "testAKIK2" - secretAccessKeyName := "testSAKN2" - secretAccessKeyKey := "testSAKK2" - sessionTokenName := "testSTN2" - sessionTokenKey := "testSTK2" - region := "region2" - endpoint := "endpoint2" - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getCronJob( - namespace, - nameLabels, - cron, - getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - version, - getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ), - ) - - client.EXPECT().ApplyCronJob(jobDef).Times(1).Return(nil) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - checkDBReady, - bucketName, - cron, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - timestamp, - nodeselector, - tolerations, - dbURL, - dbPort, - features, - version, - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} diff --git a/operator/database/kinds/backups/s3/backup/cleanup.go b/operator/database/kinds/backups/s3/backup/cleanup.go deleted file mode 100644 index 357693915d..0000000000 --- a/operator/database/kinds/backups/s3/backup/cleanup.go +++ /dev/null @@ -1,27 +0,0 @@ -package backup - -import ( - "fmt" - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" -) - -func GetCleanupFunc( - monitor mntr.Monitor, - namespace string, - backupName string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for backup to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil { - return fmt.Errorf("error while waiting for backup to be completed: %w", err) - } - monitor.Info("backup is completed, cleanup") - if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil { - return fmt.Errorf("error while trying to cleanup backup: %w", err) - } - monitor.Info("cleanup backup is completed") - return nil - } -} diff --git a/operator/database/kinds/backups/s3/backup/cleanup_test.go b/operator/database/kinds/backups/s3/backup/cleanup_test.go deleted file mode 100644 index f41ac374fc..0000000000 --- a/operator/database/kinds/backups/s3/backup/cleanup_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package backup - -import ( - "fmt" - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestBackup_Cleanup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test" - namespace := "testNs" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(fmt.Errorf("fail")) - assert.Error(t, cleanupFunc(client)) -} - -func TestBackup_Cleanup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test2" - namespace := "testNs2" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(fmt.Errorf("fail")) - assert.Error(t, cleanupFunc(client)) -} diff --git a/operator/database/kinds/backups/s3/backup/command.go b/operator/database/kinds/backups/s3/backup/command.go deleted file mode 100644 index 027774141b..0000000000 --- a/operator/database/kinds/backups/s3/backup/command.go +++ /dev/null @@ -1,53 +0,0 @@ -package backup - -import ( - "strconv" - "strings" -) - -func getBackupCommand( - timestamp string, - bucketName string, - backupName string, - certsFolder string, - accessKeyIDPath string, - secretAccessKeyPath string, - sessionTokenPath string, - region string, - endpoint string, - dbURL string, - dbPort int32, -) string { - - backupCommands := make([]string, 0) - if timestamp != "" { - backupCommands = append(backupCommands, "export "+backupNameEnv+"="+timestamp) - } else { - backupCommands = append(backupCommands, "export "+backupNameEnv+"=$(date +%Y-%m-%dT%H:%M:%SZ)") - } - - parameters := []string{ - "AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")", - "AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")", - "AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")", - "AWS_ENDPOINT=" + endpoint, - } - if region != "" { - parameters = append(parameters, "AWS_REGION="+region) - } - - backupCommands = append(backupCommands, - strings.Join([]string{ - "cockroach", - "sql", - "--certs-dir=" + certsFolder, - "--host=" + dbURL, - "--port=" + strconv.Itoa(int(dbPort)), - "-e", - "\"BACKUP TO \\\"s3://" + bucketName + "/" + backupName + "/${" + backupNameEnv + "}?" + strings.Join(parameters, "&") + "\\\";\"", - }, " ", - ), - ) - - return strings.Join(backupCommands, " && ") -} diff --git a/operator/database/kinds/backups/s3/backup/command_test.go b/operator/database/kinds/backups/s3/backup/command_test.go deleted file mode 100644 index a99718947d..0000000000 --- a/operator/database/kinds/backups/s3/backup/command_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package backup - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Command1(t *testing.T) { - timestamp := "" - bucketName := "test" - backupName := "test" - dbURL := "testDB" - dbPort := int32(80) - region := "region" - endpoint := "endpoint" - - cmd := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - equals := "export " + backupNameEnv + "=$(date +%Y-%m-%dT%H:%M:%SZ) && cockroach sql --certs-dir=" + certPath + " --host=testDB --port=80 -e \"BACKUP TO \\\"s3://test/test/${BACKUP_NAME}?AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")&AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")&AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")&AWS_ENDPOINT=endpoint&AWS_REGION=region\\\";\"" - assert.Equal(t, equals, cmd) -} - -func TestBackup_Command2(t *testing.T) { - timestamp := "test" - bucketName := "test" - backupName := "test" - dbURL := "testDB" - dbPort := int32(80) - region := "region" - endpoint := "endpoint" - - cmd := getBackupCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - equals := "export " + backupNameEnv + "=test && cockroach sql --certs-dir=" + certPath + " --host=testDB --port=80 -e \"BACKUP TO \\\"s3://test/test/${BACKUP_NAME}?AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")&AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")&AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")&AWS_ENDPOINT=endpoint&AWS_REGION=region\\\";\"" - assert.Equal(t, equals, cmd) -} diff --git a/operator/database/kinds/backups/s3/backup/job.go b/operator/database/kinds/backups/s3/backup/job.go deleted file mode 100644 index 2c2cc14b7e..0000000000 --- a/operator/database/kinds/backups/s3/backup/job.go +++ /dev/null @@ -1,127 +0,0 @@ -package backup - -import ( - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - batchv1 "k8s.io/api/batch/v1" - "k8s.io/api/batch/v1beta1" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func getCronJob( - namespace string, - nameLabels *labels.Name, - cron string, - jobSpecDef batchv1.JobSpec, -) *v1beta1.CronJob { - return &v1beta1.CronJob{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: v1beta1.CronJobSpec{ - Schedule: cron, - ConcurrencyPolicy: v1beta1.ForbidConcurrent, - JobTemplate: v1beta1.JobTemplateSpec{ - Spec: jobSpecDef, - }, - }, - } -} - -func getJob( - namespace string, - nameLabels *labels.Name, - jobSpecDef batchv1.JobSpec, -) *batchv1.Job { - return &batchv1.Job{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: jobSpecDef, - } -} - -func getJobSpecDef( - nodeselector map[string]string, - tolerations []corev1.Toleration, - accessKeyIDName string, - accessKeyIDKey string, - secretAccessKeyName string, - secretAccessKeyKey string, - sessionTokenName string, - sessionTokenKey string, - backupName string, - image string, - command string, -) batchv1.JobSpec { - return batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - } -} diff --git a/operator/database/kinds/backups/s3/backup/job_test.go b/operator/database/kinds/backups/s3/backup/job_test.go deleted file mode 100644 index c18e9070eb..0000000000 --- a/operator/database/kinds/backups/s3/backup/job_test.go +++ /dev/null @@ -1,199 +0,0 @@ -package backup - -import ( - "github.com/caos/zitadel/operator/common" - "github.com/caos/zitadel/operator/helpers" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - "testing" -) - -func TestBackup_JobSpec1(t *testing.T) { - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - backupName := "testName" - version := "testVersion" - command := "test" - accessKeyIDName := "testAKIN" - accessKeyIDKey := "testAKIK" - secretAccessKeyName := "testSAKN" - secretAccessKeyKey := "testSAKK" - sessionTokenName := "testSTN" - sessionTokenKey := "testSTK" - - equals := batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: common.BackupImage.Reference("", version), - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - } - - assert.Equal(t, equals, getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - common.BackupImage.Reference("", version), - command)) -} - -func TestBackup_JobSpec2(t *testing.T) { - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - backupName := "testName2" - version := "testVersion2" - command := "test2" - accessKeyIDName := "testAKIN2" - accessKeyIDKey := "testAKIK2" - secretAccessKeyName := "testSAKN2" - secretAccessKeyKey := "testSAKK2" - sessionTokenName := "testSTN2" - sessionTokenKey := "testSTK2" - - equals := batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: backupName, - Image: common.BackupImage.Reference("", version), - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - } - - assert.Equal(t, equals, getJobSpecDef( - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - backupName, - common.BackupImage.Reference("", version), - command, - )) -} diff --git a/operator/database/kinds/backups/s3/desired.go b/operator/database/kinds/backups/s3/desired.go deleted file mode 100644 index e00a4ae515..0000000000 --- a/operator/database/kinds/backups/s3/desired.go +++ /dev/null @@ -1,65 +0,0 @@ -package s3 - -import ( - "fmt" - - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec *Spec -} - -type Spec struct { - Verbose bool - Cron string `yaml:"cron,omitempty"` - Bucket string `yaml:"bucket,omitempty"` - Endpoint string `yaml:"endpoint,omitempty"` - Region string `yaml:"region,omitempty"` - AccessKeyID *secret.Secret `yaml:"accessKeyID,omitempty"` - ExistingAccessKeyID *secret.Existing `yaml:"existingAccessKeyID,omitempty"` - SecretAccessKey *secret.Secret `yaml:"secretAccessKey,omitempty"` - ExistingSecretAccessKey *secret.Existing `yaml:"existingSecretAccessKey,omitempty"` - SessionToken *secret.Secret `yaml:"sessionToken,omitempty"` - ExistingSessionToken *secret.Existing `yaml:"existingSessionToken,omitempty"` -} - -func (s *Spec) IsZero() bool { - if ((s.AccessKeyID == nil || s.AccessKeyID.IsZero()) && (s.ExistingAccessKeyID == nil || s.ExistingAccessKeyID.IsZero())) && - ((s.SecretAccessKey == nil || s.SecretAccessKey.IsZero()) && (s.ExistingSecretAccessKey == nil || s.ExistingSecretAccessKey.IsZero())) && - ((s.SessionToken == nil || s.SessionToken.IsZero()) && (s.ExistingSessionToken == nil || s.ExistingSessionToken.IsZero())) && - !s.Verbose && - s.Bucket == "" && - s.Cron == "" && - s.Endpoint == "" && - s.Region == "" { - return true - } - return false -} - -func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{ - Common: desiredTree.Common, - Spec: &Spec{}, - } - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, fmt.Errorf("parsing desired state failed: %s", err) - } - - return desiredKind, nil -} - -func (d *DesiredV0) validateSecrets() error { - if err := secret.ValidateSecret(d.Spec.AccessKeyID, d.Spec.ExistingAccessKeyID); err != nil { - return fmt.Errorf("validating access key id failed: %w", err) - } - if err := secret.ValidateSecret(d.Spec.SecretAccessKey, d.Spec.ExistingSecretAccessKey); err != nil { - return fmt.Errorf("validating secret access key failed: %w", err) - } - - return nil -} diff --git a/operator/database/kinds/backups/s3/desired_test.go b/operator/database/kinds/backups/s3/desired_test.go deleted file mode 100644 index 6b0899977c..0000000000 --- a/operator/database/kinds/backups/s3/desired_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package s3 - -import ( - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" - "testing" -) - -const ( - masterkey = "testMk" - cron = "testCron" - bucketName = "testBucket" - region = "testRegion" - endpoint = "testEndpoint" - akid = "testAKID" - sak = "testSAK" - st = "testST" - yamlFile = `kind: databases.caos.ch/BucketBackup -version: v0 -spec: - verbose: true - cron: testCron - bucket: testBucket - region: testRegion - endpoint: testEndpoint - accessKeyID: - encryption: AES256 - encoding: Base64 - value: l7GEXvmCT8hBXereT4FIG4j5vKQIycjS - secretAccessKey: - encryption: AES256 - encoding: Base64 - value: NWYnOpFpME-9FESqWi0bFQ3M6e0iNQw= - sessionToken: - encryption: AES256 - encoding: Base64 - value: xVY9pEXuh0Wbf2P2X_yThXwqRX08sA== -` - - yamlFileWithoutSecret = `kind: databases.caos.ch/BucketBackup -version: v0 -spec: - verbose: true - cron: testCron - bucket: testBucket - endpoint: testEndpoint - region: testRegion -` - yamlEmpty = `kind: databases.caos.ch/BucketBackup -version: v0` -) - -var ( - desired = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Endpoint: endpoint, - Region: region, - AccessKeyID: &secret.Secret{ - Value: akid, - Encryption: "AES256", - Encoding: "Base64", - }, - SecretAccessKey: &secret.Secret{ - Value: sak, - Encryption: "AES256", - Encoding: "Base64", - }, - SessionToken: &secret.Secret{ - Value: st, - Encryption: "AES256", - Encoding: "Base64", - }, - }, - } - desiredWithoutSecret = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: true, - Cron: cron, - Bucket: bucketName, - Region: region, - Endpoint: endpoint, - }, - } - desiredEmpty = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &Spec{ - Verbose: false, - Cron: "", - Bucket: "", - Endpoint: "", - Region: "", - AccessKeyID: &secret.Secret{ - Value: "", - }, - SecretAccessKey: &secret.Secret{ - Value: "", - }, - SessionToken: &secret.Secret{ - Value: "", - }, - }, - } - - desiredNil = DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - } -) - -func marshalYaml(t *testing.T, masterkey string, struc *DesiredV0) []byte { - secret.Masterkey = masterkey - data, err := yaml.Marshal(struc) - assert.NoError(t, err) - return data -} - -func unmarshalYaml(t *testing.T, masterkey string, yamlFile []byte) *tree.Tree { - secret.Masterkey = masterkey - desiredTree := &tree.Tree{} - assert.NoError(t, yaml.Unmarshal(yamlFile, desiredTree)) - return desiredTree -} - -func getDesiredTree(t *testing.T, masterkey string, desired *DesiredV0) *tree.Tree { - return unmarshalYaml(t, masterkey, marshalYaml(t, masterkey, desired)) -} - -func TestBucket_DesiredParse(t *testing.T) { - assert.Equal(t, yamlFileWithoutSecret, string(marshalYaml(t, masterkey, &desiredWithoutSecret))) - - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlFile)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.Equal(t, &desired, desiredKind) -} - -func TestBucket_DesiredNotZero(t *testing.T) { - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlFile)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.False(t, desiredKind.Spec.IsZero()) -} - -func TestBucket_DesiredZero(t *testing.T) { - desiredTree := unmarshalYaml(t, masterkey, []byte(yamlEmpty)) - desiredKind, err := ParseDesiredV0(desiredTree) - assert.NoError(t, err) - assert.True(t, desiredKind.Spec.IsZero()) -} diff --git a/operator/database/kinds/backups/s3/list.go b/operator/database/kinds/backups/s3/list.go deleted file mode 100644 index 8a74584127..0000000000 --- a/operator/database/kinds/backups/s3/list.go +++ /dev/null @@ -1,105 +0,0 @@ -package s3 - -import ( - "context" - "fmt" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/credentials" - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/secret/read" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/backups/core" - "strings" -) - -func BackupList() core.BackupListFunc { - return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) { - desiredKind, err := ParseDesiredV0(desired) - if err != nil { - return nil, fmt.Errorf("parsing desired state failed: %s", err) - } - desired.Parsed = desiredKind - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - monitor.Verbose() - } - - valueAKI, err := read.GetSecretValue(k8sClient, desiredKind.Spec.AccessKeyID, desiredKind.Spec.ExistingAccessKeyID) - if err != nil { - return nil, err - } - - valueSAK, err := read.GetSecretValue(k8sClient, desiredKind.Spec.SecretAccessKey, desiredKind.Spec.ExistingSecretAccessKey) - if err != nil { - return nil, err - } - - valueST, err := read.GetSecretValue(k8sClient, desiredKind.Spec.SessionToken, desiredKind.Spec.ExistingSessionToken) - if err != nil { - return nil, err - } - - return listFilesWithFilter(valueAKI, valueSAK, valueST, desiredKind.Spec.Region, desiredKind.Spec.Endpoint, desiredKind.Spec.Bucket, name) - } -} - -func listFilesWithFilter(akid, secretkey, sessionToken string, region string, endpoint string, bucketName, name string) ([]string, error) { - customResolver := aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) { - return aws.Endpoint{ - URL: "https://" + endpoint, - SigningRegion: region, - }, nil - }) - - cfg, err := config.LoadDefaultConfig( - context.Background(), - config.WithRegion(region), - config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(akid, secretkey, sessionToken)), - config.WithEndpointResolver(customResolver), - ) - if err != nil { - return nil, err - } - - client := s3.NewFromConfig(cfg) - - prefix := name + "/" - params := &s3.ListObjectsV2Input{ - Bucket: aws.String(bucketName), - Prefix: aws.String(prefix), - } - paginator := s3.NewListObjectsV2Paginator(client, params, func(o *s3.ListObjectsV2PaginatorOptions) { - o.Limit = 10 - }) - - names := make([]string, 0) - for paginator.HasMorePages() { - output, err := paginator.NextPage(context.Background()) - if err != nil { - return nil, err - } - for _, value := range output.Contents { - if strings.HasPrefix(*value.Key, prefix) { - parts := strings.Split(*value.Key, "/") - if len(parts) < 2 { - continue - } - found := false - for _, name := range names { - if name == parts[1] { - found = true - } - } - if !found { - names = append(names, parts[1]) - } - names = append(names) - } - - } - } - return names, nil -} diff --git a/operator/database/kinds/backups/s3/mock.go b/operator/database/kinds/backups/s3/mock.go deleted file mode 100644 index 0e4e93e1a7..0000000000 --- a/operator/database/kinds/backups/s3/mock.go +++ /dev/null @@ -1,149 +0,0 @@ -package s3 - -import ( - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - "github.com/golang/mock/gomock" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func SetQueriedForDatabases(databases, users []string) map[string]interface{} { - queried := map[string]interface{}{} - core.SetQueriedForDatabaseDBList(queried, databases, users) - - return queried -} - -func SetInstantBackup( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - backupName string, - labelsAKID map[string]string, - labelsSAK map[string]string, - labelsST map[string]string, - akid, sak, st string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: accessKeyIDName, - Namespace: namespace, - Labels: labelsAKID, - }, - StringData: map[string]string{accessKeyIDKey: akid}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretAccessKeyName, - Namespace: namespace, - Labels: labelsSAK, - }, - StringData: map[string]string{secretAccessKeyKey: sak}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: sessionTokenName, - Namespace: namespace, - Labels: labelsST, - }, - StringData: map[string]string{sessionTokenKey: st}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplyJob(gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().GetJob(namespace, backup.GetJobName(backupName)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, backup.GetJobName(backupName))) - k8sClient.EXPECT().WaitUntilJobCompleted(namespace, backup.GetJobName(backupName), gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().DeleteJob(namespace, backup.GetJobName(backupName)).Times(1).Return(nil) -} - -func SetBackup( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - labelsAKID map[string]string, - labelsSAK map[string]string, - labelsST map[string]string, - akid, sak, st string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: accessKeyIDName, - Namespace: namespace, - Labels: labelsAKID, - }, - StringData: map[string]string{accessKeyIDKey: akid}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretAccessKeyName, - Namespace: namespace, - Labels: labelsSAK, - }, - StringData: map[string]string{secretAccessKeyKey: sak}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: sessionTokenName, - Namespace: namespace, - Labels: labelsST, - }, - StringData: map[string]string{sessionTokenKey: st}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - k8sClient.EXPECT().ApplyCronJob(gomock.Any()).Times(1).Return(nil) -} - -func SetRestore( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - backupName string, - labelsAKID map[string]string, - labelsSAK map[string]string, - labelsST map[string]string, - akid, sak, st string, -) { - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: accessKeyIDName, - Namespace: namespace, - Labels: labelsAKID, - }, - StringData: map[string]string{accessKeyIDKey: akid}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretAccessKeyName, - Namespace: namespace, - Labels: labelsSAK, - }, - StringData: map[string]string{secretAccessKeyKey: sak}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: sessionTokenName, - Namespace: namespace, - Labels: labelsST, - }, - StringData: map[string]string{sessionTokenKey: st}, - Type: "Opaque", - }).MinTimes(1).MaxTimes(1).Return(nil) - k8sClient.EXPECT().ApplyJob(gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().GetJob(namespace, restore.GetJobName(backupName)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, restore.GetJobName(backupName))) - k8sClient.EXPECT().WaitUntilJobCompleted(namespace, restore.GetJobName(backupName), gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().DeleteJob(namespace, restore.GetJobName(backupName)).Times(1).Return(nil) -} diff --git a/operator/database/kinds/backups/s3/restore/adapt.go b/operator/database/kinds/backups/s3/restore/adapt.go deleted file mode 100644 index 9bf87648fd..0000000000 --- a/operator/database/kinds/backups/s3/restore/adapt.go +++ /dev/null @@ -1,115 +0,0 @@ -package restore - -import ( - "time" - - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - corev1 "k8s.io/api/core/v1" -) - -const ( - Instant = "restore" - defaultMode = int32(256) - certPath = "/cockroach/cockroach-certs" - accessKeyIDPath = "/secrets/accessaccountkey" - secretAccessKeyPath = "/secrets/secretaccesskey" - sessionTokenPath = "/secrets/sessiontoken" - jobPrefix = "backup-" - jobSuffix = "-restore" - internalSecretName = "client-certs" - rootSecretName = "cockroachdb.client.root" - timeout = 15 * time.Minute -) - -func AdaptFunc( - monitor mntr.Monitor, - backupName string, - namespace string, - componentLabels *labels.Component, - bucketName string, - timestamp string, - accessKeyIDName string, - accessKeyIDKey string, - secretAccessKeyName string, - secretAccessKeyKey string, - sessionTokenName string, - sessionTokenKey string, - region string, - endpoint string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - checkDBReady operator.EnsureFunc, - dbURL string, - dbPort int32, - image string, -) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - err error, -) { - - jobName := jobPrefix + backupName + jobSuffix - command := getCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - - jobdef := getJob( - namespace, - labels.MustForName(componentLabels, GetJobName(backupName)), - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - image, - command, - ) - - destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyJ), - } - - queryJ, err := job.AdaptFuncToEnsure(jobdef) - if err != nil { - return nil, nil, err - } - - queriers := []operator.QueryFunc{ - operator.EnsureFuncToQueryFunc(checkDBReady), - operator.ResourceQueryToZitadelQuery(queryJ), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - - nil -} - -func GetJobName(backupName string) string { - return jobPrefix + backupName + jobSuffix -} diff --git a/operator/database/kinds/backups/s3/restore/adapt_test.go b/operator/database/kinds/backups/s3/restore/adapt_test.go deleted file mode 100644 index cd14d1f5ea..0000000000 --- a/operator/database/kinds/backups/s3/restore/adapt_test.go +++ /dev/null @@ -1,196 +0,0 @@ -package restore - -import ( - "github.com/caos/zitadel/operator/common" - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestBackup_Adapt1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - monitor := mntr.Monitor{} - namespace := "testNs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - timestamp := "testTs" - backupName := "testName2" - bucketName := "testBucket2" - version := "testVersion" - accessKeyIDName := "testAKIN" - accessKeyIDKey := "testAKIK" - secretAccessKeyName := "testSAKN" - secretAccessKeyKey := "testSAKK" - sessionTokenName := "testSTN" - sessionTokenKey := "testSTK" - region := "region" - endpoint := "endpoint" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "testVersion"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - common.BackupImage.Reference("", version), - getCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - bucketName, - timestamp, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - nodeselector, - tolerations, - checkDBReady, - dbURL, - dbPort, - common.BackupImage.Reference("", version), - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} - -func TestBackup_Adapt2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - monitor := mntr.Monitor{} - namespace := "testNs2" - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - timestamp := "testTs" - backupName := "testName2" - bucketName := "testBucket2" - version := "testVersion2" - accessKeyIDName := "testAKIN2" - accessKeyIDKey := "testAKIK2" - secretAccessKeyName := "testSAKN2" - secretAccessKeyKey := "testSAKK2" - sessionTokenName := "testSTN2" - sessionTokenKey := "testSTK2" - region := "region2" - endpoint := "endpoint2" - dbURL := "testDB" - dbPort := int32(80) - jobName := GetJobName(backupName) - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "testVersion2"), "testComponent2") - nameLabels := labels.MustForName(componentLabels, jobName) - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - jobDef := getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - common.BackupImage.Reference("", version), - getCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ), - ) - - client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) - client.EXPECT().GetJob(jobDef.Namespace, jobDef.Name).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobName)) - - query, _, err := AdaptFunc( - monitor, - backupName, - namespace, - componentLabels, - bucketName, - timestamp, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - region, - endpoint, - nodeselector, - tolerations, - checkDBReady, - dbURL, - dbPort, - common.BackupImage.Reference("", version), - ) - - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} diff --git a/operator/database/kinds/backups/s3/restore/cleanup.go b/operator/database/kinds/backups/s3/restore/cleanup.go deleted file mode 100644 index 252fddb4bb..0000000000 --- a/operator/database/kinds/backups/s3/restore/cleanup.go +++ /dev/null @@ -1,27 +0,0 @@ -package restore - -import ( - "fmt" - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" -) - -func GetCleanupFunc( - monitor mntr.Monitor, - namespace, - backupName string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for restore to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil { - return fmt.Errorf("error while waiting for restore to be completed: %s", err.Error()) - } - monitor.Info("restore is completed, cleanup") - if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil { - return fmt.Errorf("error while trying to cleanup restore: %s", err.Error()) - } - monitor.Info("restore cleanup is completed") - return nil - } -} diff --git a/operator/database/kinds/backups/s3/restore/cleanup_test.go b/operator/database/kinds/backups/s3/restore/cleanup_test.go deleted file mode 100644 index 81671b1f30..0000000000 --- a/operator/database/kinds/backups/s3/restore/cleanup_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package restore - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Cleanup1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test" - namespace := "testNs" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} - -func TestBackup_Cleanup2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - name := "test2" - namespace := "testNs2" - - cleanupFunc := GetCleanupFunc(monitor, namespace, name) - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(nil) - client.EXPECT().DeleteJob(namespace, GetJobName(name)).Times(1) - assert.NoError(t, cleanupFunc(client)) - - client.EXPECT().WaitUntilJobCompleted(namespace, GetJobName(name), timeout).Times(1).Return(errors.New("fail")) - assert.Error(t, cleanupFunc(client)) -} diff --git a/operator/database/kinds/backups/s3/restore/command.go b/operator/database/kinds/backups/s3/restore/command.go deleted file mode 100644 index d739b70153..0000000000 --- a/operator/database/kinds/backups/s3/restore/command.go +++ /dev/null @@ -1,48 +0,0 @@ -package restore - -import ( - "strconv" - "strings" -) - -func getCommand( - timestamp string, - bucketName string, - backupName string, - certsFolder string, - accessKeyIDPath string, - secretAccessKeyPath string, - sessionTokenPath string, - region string, - endpoint string, - dbURL string, - dbPort int32, -) string { - - backupCommands := make([]string, 0) - - parameters := []string{ - "AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")", - "AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")", - "AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")", - "AWS_ENDPOINT=" + endpoint, - } - if region != "" { - parameters = append(parameters, "AWS_REGION="+region) - } - - backupCommands = append(backupCommands, - strings.Join([]string{ - "cockroach", - "sql", - "--certs-dir=" + certsFolder, - "--host=" + dbURL, - "--port=" + strconv.Itoa(int(dbPort)), - "-e", - "\"RESTORE FROM \\\"s3://" + bucketName + "/" + backupName + "/" + timestamp + "?" + strings.Join(parameters, "&") + "\\\";\"", - }, " ", - ), - ) - - return strings.Join(backupCommands, " && ") -} diff --git a/operator/database/kinds/backups/s3/restore/command_test.go b/operator/database/kinds/backups/s3/restore/command_test.go deleted file mode 100644 index c8740b267c..0000000000 --- a/operator/database/kinds/backups/s3/restore/command_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package restore - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestBackup_Command1(t *testing.T) { - timestamp := "test1" - bucketName := "testBucket" - backupName := "testBackup" - dbURL := "testDB" - dbPort := int32(80) - region := "region" - endpoint := "endpoint" - - cmd := getCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - - equals := "cockroach sql --certs-dir=" + certPath + " --host=testDB --port=80 -e \"RESTORE FROM \\\"s3://testBucket/testBackup/test1?AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")&AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")&AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")&AWS_ENDPOINT=endpoint&AWS_REGION=region\\\";\"" - assert.Equal(t, equals, cmd) -} - -func TestBackup_Command2(t *testing.T) { - timestamp := "test2" - bucketName := "testBucket" - backupName := "testBackup" - dbURL := "testDB2" - dbPort := int32(81) - region := "region2" - endpoint := "endpoint2" - - cmd := getCommand( - timestamp, - bucketName, - backupName, - certPath, - accessKeyIDPath, - secretAccessKeyPath, - sessionTokenPath, - region, - endpoint, - dbURL, - dbPort, - ) - equals := "cockroach sql --certs-dir=" + certPath + " --host=testDB2 --port=81 -e \"RESTORE FROM \\\"s3://testBucket/testBackup/test2?AWS_ACCESS_KEY_ID=$(cat " + accessKeyIDPath + ")&AWS_SECRET_ACCESS_KEY=$(cat " + secretAccessKeyPath + ")&AWS_SESSION_TOKEN=$(cat " + sessionTokenPath + ")&AWS_ENDPOINT=endpoint2&AWS_REGION=region2\\\";\"" - assert.Equal(t, equals, cmd) -} diff --git a/operator/database/kinds/backups/s3/restore/job.go b/operator/database/kinds/backups/s3/restore/job.go deleted file mode 100644 index 7942b6ab41..0000000000 --- a/operator/database/kinds/backups/s3/restore/job.go +++ /dev/null @@ -1,98 +0,0 @@ -package restore - -import ( - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func getJob( - namespace string, - nameLabels *labels.Name, - nodeselector map[string]string, - tolerations []corev1.Toleration, - accessKeyIDName string, - accessKeyIDKey string, - secretAccessKeyName string, - secretAccessKeyKey string, - sessionTokenName string, - sessionTokenKey string, - image string, - command string, - -) *batchv1.Job { - return &batchv1.Job{ - ObjectMeta: v1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - RestartPolicy: corev1.RestartPolicyNever, - Containers: []corev1.Container{{ - Name: nameLabels.Name(), - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - }, - } -} diff --git a/operator/database/kinds/backups/s3/restore/job_test.go b/operator/database/kinds/backups/s3/restore/job_test.go deleted file mode 100644 index 8bbe1c3016..0000000000 --- a/operator/database/kinds/backups/s3/restore/job_test.go +++ /dev/null @@ -1,240 +0,0 @@ -package restore - -import ( - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" -) - -func TestBackup_Job1(t *testing.T) { - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{ - {Key: "testKey", Operator: "testOp"}} - image := "testVersion" - command := "test" - accessKeyIDName := "testAKIN" - accessKeyIDKey := "testAKIK" - secretAccessKeyName := "testSAKN" - secretAccessKeyKey := "testSAKK" - sessionTokenName := "testSTN" - sessionTokenKey := "testSTK" - jobName := "testJob" - namespace := "testNs" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": jobName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testOpVersion", - "caos.ch/apiversion": "testVersion", - "caos.ch/kind": "testKind"} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testOpVersion"), "testKind", "testVersion"), "testComponent") - nameLabels := labels.MustForName(componentLabels, jobName) - - equals := - &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: jobName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - }, - } - - assert.Equal(t, equals, getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - image, - command, - )) -} - -func TestBackup_Job2(t *testing.T) { - nodeselector := map[string]string{"test2": "test2"} - tolerations := []corev1.Toleration{ - {Key: "testKey2", Operator: "testOp2"}} - image := "testVersion2" - command := "test2" - accessKeyIDName := "testAKIN2" - accessKeyIDKey := "testAKIK2" - secretAccessKeyName := "testSAKN2" - secretAccessKeyKey := "testSAKK2" - sessionTokenName := "testSTN2" - sessionTokenKey := "testSTK2" - jobName := "testJob2" - namespace := "testNs2" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": jobName, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testOpVersion2", - "caos.ch/apiversion": "testVersion2", - "caos.ch/kind": "testKind2"} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testOpVersion2"), "testKind2", "testVersion2"), "testComponent2") - nameLabels := labels.MustForName(componentLabels, jobName) - - equals := - &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - NodeSelector: nodeselector, - Tolerations: tolerations, - Containers: []corev1.Container{{ - Name: jobName, - Image: image, - Command: []string{ - "/bin/bash", - "-c", - command, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: internalSecretName, - MountPath: certPath, - }, { - Name: accessKeyIDKey, - SubPath: accessKeyIDKey, - MountPath: accessKeyIDPath, - }, { - Name: secretAccessKeyKey, - SubPath: secretAccessKeyKey, - MountPath: secretAccessKeyPath, - }, { - Name: sessionTokenKey, - SubPath: sessionTokenKey, - MountPath: sessionTokenPath, - }}, - ImagePullPolicy: corev1.PullIfNotPresent, - }}, - Volumes: []corev1.Volume{{ - Name: internalSecretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecretName, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: accessKeyIDKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: accessKeyIDName, - }, - }, - }, { - Name: secretAccessKeyKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretAccessKeyName, - }, - }, - }, { - Name: sessionTokenKey, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: sessionTokenName, - }, - }, - }}, - }, - }, - }, - } - - assert.Equal(t, equals, getJob( - namespace, - nameLabels, - nodeselector, - tolerations, - accessKeyIDName, - accessKeyIDKey, - secretAccessKeyName, - secretAccessKeyKey, - sessionTokenName, - sessionTokenKey, - image, - command)) -} diff --git a/operator/database/kinds/backups/s3/secrets.go b/operator/database/kinds/backups/s3/secrets.go deleted file mode 100644 index 809e09a176..0000000000 --- a/operator/database/kinds/backups/s3/secrets.go +++ /dev/null @@ -1,54 +0,0 @@ -package s3 - -import ( - "github.com/caos/orbos/pkg/secret" -) - -func getSecretsMap(desiredKind *DesiredV0) (map[string]*secret.Secret, map[string]*secret.Existing) { - - var ( - secrets = make(map[string]*secret.Secret, 0) - existing = make(map[string]*secret.Existing, 0) - ) - if desiredKind.Spec == nil { - desiredKind.Spec = &Spec{} - } - - if desiredKind.Spec.AccessKeyID == nil { - desiredKind.Spec.AccessKeyID = &secret.Secret{} - } - - if desiredKind.Spec.ExistingAccessKeyID == nil { - desiredKind.Spec.ExistingAccessKeyID = &secret.Existing{} - } - - akikey := "accesskeyid" - secrets[akikey] = desiredKind.Spec.AccessKeyID - existing[akikey] = desiredKind.Spec.ExistingAccessKeyID - - if desiredKind.Spec.SecretAccessKey == nil { - desiredKind.Spec.SecretAccessKey = &secret.Secret{} - } - - if desiredKind.Spec.ExistingSecretAccessKey == nil { - desiredKind.Spec.ExistingSecretAccessKey = &secret.Existing{} - } - - sakkey := "secretaccesskey" - secrets[sakkey] = desiredKind.Spec.SecretAccessKey - existing[sakkey] = desiredKind.Spec.ExistingSecretAccessKey - - if desiredKind.Spec.SessionToken == nil { - desiredKind.Spec.SessionToken = &secret.Secret{} - } - - if desiredKind.Spec.ExistingSessionToken == nil { - desiredKind.Spec.ExistingSessionToken = &secret.Existing{} - } - - stkey := "sessiontoken" - secrets[stkey] = desiredKind.Spec.SessionToken - existing[stkey] = desiredKind.Spec.ExistingSessionToken - - return secrets, existing -} diff --git a/operator/database/kinds/backups/s3/secrets_test.go b/operator/database/kinds/backups/s3/secrets_test.go deleted file mode 100644 index ada753df76..0000000000 --- a/operator/database/kinds/backups/s3/secrets_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package s3 - -import ( - "testing" - - "github.com/caos/orbos/pkg/secret" - "github.com/stretchr/testify/assert" -) - -func TestBucket_getSecretsFull(t *testing.T) { - secrets, existing := getSecretsMap(&desired) - assert.Equal(t, desired.Spec.AccessKeyID, secrets["accesskeyid"]) - assert.Equal(t, desired.Spec.ExistingAccessKeyID, existing["accesskeyid"]) - assert.Equal(t, desired.Spec.SecretAccessKey, secrets["secretaccesskey"]) - assert.Equal(t, desired.Spec.ExistingSecretAccessKey, existing["secretaccesskey"]) - assert.Equal(t, desired.Spec.SessionToken, secrets["sessiontoken"]) - assert.Equal(t, desired.Spec.ExistingSessionToken, existing["sessiontoken"]) -} - -func TestBucket_getSecretsEmpty(t *testing.T) { - secrets, existing := getSecretsMap(&desiredWithoutSecret) - assert.Equal(t, &secret.Secret{}, secrets["accesskeyid"]) - assert.Equal(t, &secret.Existing{}, existing["accesskeyid"]) - assert.Equal(t, &secret.Secret{}, secrets["secretaccesskey"]) - assert.Equal(t, &secret.Existing{}, existing["secretaccesskey"]) - assert.Equal(t, &secret.Secret{}, secrets["sessiontoken"]) - assert.Equal(t, &secret.Existing{}, existing["sessiontoken"]) -} - -func TestBucket_getSecretsNil(t *testing.T) { - secrets, existing := getSecretsMap(&desiredNil) - assert.Equal(t, &secret.Secret{}, secrets["accesskeyid"]) - assert.Equal(t, &secret.Existing{}, existing["accesskeyid"]) - assert.Equal(t, &secret.Secret{}, secrets["secretaccesskey"]) - assert.Equal(t, &secret.Existing{}, existing["secretaccesskey"]) - assert.Equal(t, &secret.Secret{}, secrets["sessiontoken"]) - assert.Equal(t, &secret.Existing{}, existing["sessiontoken"]) -} diff --git a/operator/database/kinds/databases/core/current.go b/operator/database/kinds/databases/core/current.go deleted file mode 100644 index 1a28bff49c..0000000000 --- a/operator/database/kinds/databases/core/current.go +++ /dev/null @@ -1,66 +0,0 @@ -package core - -import ( - "crypto/rsa" - "errors" - - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" -) - -const queriedName = "database" - -type DatabaseCurrent interface { - GetURL() string - GetPort() string - GetReadyQuery() operator.EnsureFunc - GetCertificateKey() *rsa.PrivateKey - SetCertificateKey(*rsa.PrivateKey) - GetCertificate() []byte - SetCertificate([]byte) - GetAddUserFunc() func(user string) (operator.QueryFunc, error) - GetDeleteUserFunc() func(user string) (operator.DestroyFunc, error) - GetListUsersFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) - GetListDatabasesFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) -} - -func ParseQueriedForDatabase(queried map[string]interface{}) (DatabaseCurrent, error) { - queriedDB, ok := queried[queriedName] - if !ok { - return nil, errors.New("no current state for database found") - } - currentDBTree, ok := queriedDB.(*tree.Tree) - if !ok { - return nil, errors.New("current state does not fullfil interface") - } - currentDB, ok := currentDBTree.Parsed.(DatabaseCurrent) - if !ok { - return nil, errors.New("current state does not fullfil interface") - } - - return currentDB, nil -} - -func SetQueriedForDatabase(queried map[string]interface{}, databaseCurrent *tree.Tree) { - queried[queriedName] = databaseCurrent -} - -func SetQueriedForDatabaseDBList(queried map[string]interface{}, databases, users []string) { - currentDBList := &CurrentDBList{ - Common: &tree.Common{ - Kind: "DBList", - }, - Current: &DatabaseCurrentDBList{ - Databases: databases, - Users: users, - }, - } - currentDBList.Common.OverwriteVersion("V0") - - currentDB := &tree.Tree{ - Parsed: currentDBList, - } - - SetQueriedForDatabase(queried, currentDB) -} diff --git a/operator/database/kinds/databases/core/dblist.go b/operator/database/kinds/databases/core/dblist.go deleted file mode 100644 index 5bdfdad3f4..0000000000 --- a/operator/database/kinds/databases/core/dblist.go +++ /dev/null @@ -1,68 +0,0 @@ -package core - -import ( - "crypto/rsa" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" -) - -var current DatabaseCurrent = &CurrentDBList{} - -type CurrentDBList struct { - Common *tree.Common `yaml:",inline"` - Current *DatabaseCurrentDBList -} - -type DatabaseCurrentDBList struct { - Databases []string - Users []string -} - -func (c *CurrentDBList) GetURL() string { - return "" -} - -func (c *CurrentDBList) GetPort() string { - return "" -} - -func (c *CurrentDBList) GetReadyQuery() operator.EnsureFunc { - return nil -} - -func (c *CurrentDBList) GetCertificateKey() *rsa.PrivateKey { - return nil -} - -func (c *CurrentDBList) SetCertificateKey(key *rsa.PrivateKey) { - return -} - -func (c *CurrentDBList) GetCertificate() []byte { - return nil -} - -func (c *CurrentDBList) SetCertificate(cert []byte) { - return -} - -func (c *CurrentDBList) GetListDatabasesFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) { - return func(k8sClient kubernetes.ClientInt) ([]string, error) { - return c.Current.Databases, nil - } -} - -func (c *CurrentDBList) GetListUsersFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) { - return func(k8sClient kubernetes.ClientInt) ([]string, error) { - return c.Current.Users, nil - } -} - -func (c *CurrentDBList) GetAddUserFunc() func(user string) (operator.QueryFunc, error) { - return nil -} - -func (c *CurrentDBList) GetDeleteUserFunc() func(user string) (operator.DestroyFunc, error) { - return nil -} diff --git a/operator/database/kinds/databases/core/generate.go b/operator/database/kinds/databases/core/generate.go deleted file mode 100644 index 93bf62a361..0000000000 --- a/operator/database/kinds/databases/core/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package core - -//go:generate mockgen -source current.go -package coremock -destination mock/current.mock.go github.com/caos/internal/operator/database/kinds/databases/core DatabaseCurrent diff --git a/operator/database/kinds/databases/core/mock/current.mock.go b/operator/database/kinds/databases/core/mock/current.mock.go deleted file mode 100644 index 40c7f8a4a7..0000000000 --- a/operator/database/kinds/databases/core/mock/current.mock.go +++ /dev/null @@ -1,186 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: current.go - -// Package coremock is a generated GoMock package. -package coremock - -import ( - rsa "crypto/rsa" - kubernetes "github.com/caos/orbos/pkg/kubernetes" - operator "github.com/caos/zitadel/operator" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockDatabaseCurrent is a mock of DatabaseCurrent interface -type MockDatabaseCurrent struct { - ctrl *gomock.Controller - recorder *MockDatabaseCurrentMockRecorder -} - -// MockDatabaseCurrentMockRecorder is the mock recorder for MockDatabaseCurrent -type MockDatabaseCurrentMockRecorder struct { - mock *MockDatabaseCurrent -} - -// NewMockDatabaseCurrent creates a new mock instance -func NewMockDatabaseCurrent(ctrl *gomock.Controller) *MockDatabaseCurrent { - mock := &MockDatabaseCurrent{ctrl: ctrl} - mock.recorder = &MockDatabaseCurrentMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockDatabaseCurrent) EXPECT() *MockDatabaseCurrentMockRecorder { - return m.recorder -} - -// GetURL mocks base method -func (m *MockDatabaseCurrent) GetURL() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetURL") - ret0, _ := ret[0].(string) - return ret0 -} - -// GetURL indicates an expected call of GetURL -func (mr *MockDatabaseCurrentMockRecorder) GetURL() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetURL", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetURL)) -} - -// GetPort mocks base method -func (m *MockDatabaseCurrent) GetPort() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPort") - ret0, _ := ret[0].(string) - return ret0 -} - -// GetPort indicates an expected call of GetPort -func (mr *MockDatabaseCurrentMockRecorder) GetPort() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPort", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetPort)) -} - -// GetReadyQuery mocks base method -func (m *MockDatabaseCurrent) GetReadyQuery() operator.EnsureFunc { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReadyQuery") - ret0, _ := ret[0].(operator.EnsureFunc) - return ret0 -} - -// GetReadyQuery indicates an expected call of GetReadyQuery -func (mr *MockDatabaseCurrentMockRecorder) GetReadyQuery() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReadyQuery", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetReadyQuery)) -} - -// GetCertificateKey mocks base method -func (m *MockDatabaseCurrent) GetCertificateKey() *rsa.PrivateKey { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCertificateKey") - ret0, _ := ret[0].(*rsa.PrivateKey) - return ret0 -} - -// GetCertificateKey indicates an expected call of GetCertificateKey -func (mr *MockDatabaseCurrentMockRecorder) GetCertificateKey() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCertificateKey", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetCertificateKey)) -} - -// SetCertificateKey mocks base method -func (m *MockDatabaseCurrent) SetCertificateKey(arg0 *rsa.PrivateKey) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetCertificateKey", arg0) -} - -// SetCertificateKey indicates an expected call of SetCertificateKey -func (mr *MockDatabaseCurrentMockRecorder) SetCertificateKey(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCertificateKey", reflect.TypeOf((*MockDatabaseCurrent)(nil).SetCertificateKey), arg0) -} - -// GetCertificate mocks base method -func (m *MockDatabaseCurrent) GetCertificate() []byte { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCertificate") - ret0, _ := ret[0].([]byte) - return ret0 -} - -// GetCertificate indicates an expected call of GetCertificate -func (mr *MockDatabaseCurrentMockRecorder) GetCertificate() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCertificate", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetCertificate)) -} - -// SetCertificate mocks base method -func (m *MockDatabaseCurrent) SetCertificate(arg0 []byte) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetCertificate", arg0) -} - -// SetCertificate indicates an expected call of SetCertificate -func (mr *MockDatabaseCurrentMockRecorder) SetCertificate(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCertificate", reflect.TypeOf((*MockDatabaseCurrent)(nil).SetCertificate), arg0) -} - -// GetAddUserFunc mocks base method -func (m *MockDatabaseCurrent) GetAddUserFunc() func(string) (operator.QueryFunc, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAddUserFunc") - ret0, _ := ret[0].(func(string) (operator.QueryFunc, error)) - return ret0 -} - -// GetAddUserFunc indicates an expected call of GetAddUserFunc -func (mr *MockDatabaseCurrentMockRecorder) GetAddUserFunc() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAddUserFunc", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetAddUserFunc)) -} - -// GetDeleteUserFunc mocks base method -func (m *MockDatabaseCurrent) GetDeleteUserFunc() func(string) (operator.DestroyFunc, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDeleteUserFunc") - ret0, _ := ret[0].(func(string) (operator.DestroyFunc, error)) - return ret0 -} - -// GetDeleteUserFunc indicates an expected call of GetDeleteUserFunc -func (mr *MockDatabaseCurrentMockRecorder) GetDeleteUserFunc() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeleteUserFunc", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetDeleteUserFunc)) -} - -// GetListUsersFunc mocks base method -func (m *MockDatabaseCurrent) GetListUsersFunc() func(kubernetes.ClientInt) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetListUsersFunc") - ret0, _ := ret[0].(func(kubernetes.ClientInt) ([]string, error)) - return ret0 -} - -// GetListUsersFunc indicates an expected call of GetListUsersFunc -func (mr *MockDatabaseCurrentMockRecorder) GetListUsersFunc() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetListUsersFunc", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetListUsersFunc)) -} - -// GetListDatabasesFunc mocks base method -func (m *MockDatabaseCurrent) GetListDatabasesFunc() func(kubernetes.ClientInt) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetListDatabasesFunc") - ret0, _ := ret[0].(func(kubernetes.ClientInt) ([]string, error)) - return ret0 -} - -// GetListDatabasesFunc indicates an expected call of GetListDatabasesFunc -func (mr *MockDatabaseCurrentMockRecorder) GetListDatabasesFunc() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetListDatabasesFunc", reflect.TypeOf((*MockDatabaseCurrent)(nil).GetListDatabasesFunc)) -} diff --git a/operator/database/kinds/databases/databases.go b/operator/database/kinds/databases/databases.go deleted file mode 100644 index 7c6c26d9b1..0000000000 --- a/operator/database/kinds/databases/databases.go +++ /dev/null @@ -1,76 +0,0 @@ -package databases - -import ( - "fmt" - - core "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/database/kinds/databases/managed" - "github.com/caos/zitadel/operator/database/kinds/databases/provided" -) - -const ( - component = "database" -) - -func ComponentSelector() *labels.Selector { - return labels.OpenComponentSelector("ZITADEL", component) -} - -func Adapt( - monitor mntr.Monitor, - desiredTree *tree.Tree, - currentTree *tree.Tree, - namespace string, - apiLabels *labels.API, - timestamp string, - nodeselector map[string]string, - tolerations []core.Toleration, - version string, - features []string, - customImageRegistry string, -) ( - query operator.QueryFunc, - destroy operator.DestroyFunc, - configure operator.ConfigureFunc, - secrets map[string]*secret.Secret, - existing map[string]*secret.Existing, - migrate bool, - err error, -) { - componentLabels := labels.MustForComponent(apiLabels, component) - internalMonitor := monitor.WithField("component", component) - - switch desiredTree.Common.Kind { - case "databases.caos.ch/CockroachDB": - return managed.Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, customImageRegistry)(internalMonitor, desiredTree, currentTree) - case "databases.caos.ch/ProvidedDatabase": - return provided.Adapter()(internalMonitor, desiredTree, currentTree) - default: - return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown database kind %s: %w", desiredTree.Common.Kind, err)) - } -} - -func GetBackupList( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desiredTree *tree.Tree, -) ( - []string, - error, -) { - switch desiredTree.Common.Kind { - case "databases.caos.ch/CockroachDB": - return managed.BackupList()(monitor, k8sClient, desiredTree) - case "databases.caos.ch/ProvidedDatabse": - return nil, mntr.ToUserError(fmt.Errorf("no backups supported for database kind %s", desiredTree.Common.Kind)) - default: - return nil, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind)) - } -} diff --git a/operator/database/kinds/databases/managed/adapt.go b/operator/database/kinds/databases/managed/adapt.go deleted file mode 100644 index caf2eb81b2..0000000000 --- a/operator/database/kinds/databases/managed/adapt.go +++ /dev/null @@ -1,284 +0,0 @@ -package managed - -import ( - "fmt" - "strconv" - "strings" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/pdb" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/common" - "github.com/caos/zitadel/operator/database/kinds/backups" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/rbac" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/services" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/statefulset" -) - -const ( - SfsName = "cockroachdb" - pdbName = SfsName + "-budget" - serviceAccountName = SfsName - PublicServiceName = SfsName + "-public" - privateServiceName = SfsName - cockroachPort = int32(26257) - cockroachHTTPPort = int32(8080) - Clean = "clean" - DBReady = "dbready" -) - -func Adapter( - componentLabels *labels.Component, - namespace string, - timestamp string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - version string, - features []string, - customImageRegistry string, -) operator.AdaptFunc { - - return func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, - ) ( - _ operator.QueryFunc, - _ operator.DestroyFunc, - _ operator.ConfigureFunc, - _ map[string]*secret.Secret, - _ map[string]*secret.Existing, - migrate bool, - err error, - ) { - - defer func() { - if err != nil { - err = fmt.Errorf("adapting managed database failed: %w", err) - } - }() - - var ( - internalMonitor = monitor.WithField("kind", "cockroachdb") - allSecrets = make(map[string]*secret.Secret) - allExisting = make(map[string]*secret.Existing) - ) - - desiredKind, err := parseDesiredV0(desired) - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - storageCapacity, err := resource.ParseQuantity(desiredKind.Spec.StorageCapacity) - if err != nil { - return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("parsing storage capacity format failed: %w", err)) - } - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - internalMonitor.Verbose() - } - - var ( - isFeatureDatabase bool - isFeatureClean bool - ) - for _, feature := range features { - switch feature { - case "database": - isFeatureDatabase = true - case Clean: - isFeatureClean = true - } - } - - queryCert, destroyCert, addUser, deleteUser, listUsers, err := certificate.AdaptFunc(internalMonitor, namespace, componentLabels, desiredKind.Spec.ClusterDns, isFeatureDatabase) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - addRoot, err := addUser("root") - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - destroyRoot, err := deleteUser("root") - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryRBAC, destroyRBAC, err := rbac.AdaptFunc(internalMonitor, namespace, labels.MustForName(componentLabels, serviceAccountName)) - - cockroachNameLabels := labels.MustForName(componentLabels, SfsName) - cockroachSelector := labels.DeriveNameSelector(cockroachNameLabels, false) - cockroachSelectabel := labels.AsSelectable(cockroachNameLabels) - querySFS, destroySFS, ensureInit, checkDBReady, listDatabases, err := statefulset.AdaptFunc( - internalMonitor, - cockroachSelectabel, - cockroachSelector, - desiredKind.Spec.Force, - namespace, - common.CockroachImage.Reference(customImageRegistry), - serviceAccountName, - desiredKind.Spec.ReplicaCount, - storageCapacity, - cockroachPort, - cockroachHTTPPort, - desiredKind.Spec.StorageClass, - desiredKind.Spec.NodeSelector, - desiredKind.Spec.Tolerations, - desiredKind.Spec.Resources, - desiredKind.Spec.Cache, - desiredKind.Spec.MaxSQLMemory, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryS, destroyS, err := services.AdaptFunc( - internalMonitor, - namespace, - labels.MustForName(componentLabels, PublicServiceName), - labels.MustForName(componentLabels, privateServiceName), - cockroachSelector, - cockroachPort, - cockroachHTTPPort, - ) - - queryPDB, err := pdb.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, pdbName), cockroachSelector, "1") - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - currentDB := &Current{ - Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false), - Current: &CurrentDB{ - CA: &certificate.Current{}, - }, - } - current.Parsed = currentDB - - var ( - queriers = make([]operator.QueryFunc, 0) - destroyers = make([]operator.DestroyFunc, 0) - configurers = make([]operator.ConfigureFunc, 0) - ) - if isFeatureDatabase { - queriers = append(queriers, - queryRBAC, - queryCert, - addRoot, - operator.ResourceQueryToZitadelQuery(querySFS), - operator.ResourceQueryToZitadelQuery(queryPDB), - queryS, - operator.EnsureFuncToQueryFunc(ensureInit), - ) - destroyers = append(destroyers, - destroyS, - operator.ResourceDestroyToZitadelDestroy(destroySFS), - destroyRBAC, - destroyCert, - destroyRoot, - ) - } - - if isFeatureClean { - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery( - statefulset.CleanPVCs( - monitor, - namespace, - cockroachSelectabel, - desiredKind.Spec.ReplicaCount, - ), - ), - operator.EnsureFuncToQueryFunc(ensureInit), - operator.EnsureFuncToQueryFunc(checkDBReady), - ) - } - - if desiredKind.Spec.Backups != nil { - - oneBackup := false - for backupName := range desiredKind.Spec.Backups { - if timestamp != "" && strings.HasPrefix(timestamp, backupName) { - oneBackup = true - } - } - - for backupName, desiredBackup := range desiredKind.Spec.Backups { - currentBackup := &tree.Tree{} - if timestamp == "" || !oneBackup || (timestamp != "" && strings.HasPrefix(timestamp, backupName)) { - queryB, destroyB, configureB, secrets, existing, migrateB, err := backups.Adapt( - internalMonitor, - desiredBackup, - currentBackup, - backupName, - namespace, - componentLabels, - checkDBReady, - strings.TrimPrefix(timestamp, backupName+"."), - nodeselector, - tolerations, - version, - PublicServiceName, - cockroachPort, - features, - customImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - migrate = migrate || migrateB - - secret.AppendSecrets(backupName, allSecrets, secrets, allExisting, existing) - destroyers = append(destroyers, destroyB) - queriers = append(queriers, queryB) - configurers = append(configurers, configureB) - } - } - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - queriedCurrentDB, err := core.ParseQueriedForDatabase(queried) - if err != nil || queriedCurrentDB == nil { - // TODO: query system state - currentDB.Current.Port = strconv.Itoa(int(cockroachPort)) - currentDB.Current.URL = PublicServiceName - currentDB.Current.ReadyFunc = checkDBReady - currentDB.Current.AddUserFunc = addUser - currentDB.Current.DeleteUserFunc = deleteUser - currentDB.Current.ListUsersFunc = listUsers - currentDB.Current.ListDatabasesFunc = listDatabases - - core.SetQueriedForDatabase(queried, current) - internalMonitor.Info("set current state of managed database") - } - - ensure, err := operator.QueriersToEnsureFunc(internalMonitor, true, queriers, k8sClient, queried) - return ensure, err - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, gitops bool) error { - for i := range configurers { - if err := configurers[i](k8sClient, queried, gitops); err != nil { - return err - } - } - return nil - }, - allSecrets, - allExisting, - migrate, - nil - } -} diff --git a/operator/database/kinds/databases/managed/adapt_backup_test.go b/operator/database/kinds/databases/managed/adapt_backup_test.go deleted file mode 100644 index 1ee1ef6108..0000000000 --- a/operator/database/kinds/databases/managed/adapt_backup_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package managed - -import ( - "testing" - "time" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func getTreeWithDBAndBackup(t *testing.T, masterkey string, saJson string, backupName string) *tree.Tree { - - bucketDesired := getDesiredTree(t, masterkey, &bucket.DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false), - Spec: &bucket.Spec{ - Verbose: true, - Cron: "testCron", - Bucket: "testBucket", - ServiceAccountJSON: &secret.Secret{ - Value: saJson, - }, - }, - }) - bucketDesiredKind, err := bucket.ParseDesiredV0(bucketDesired) - assert.NoError(t, err) - bucketDesired.Parsed = bucketDesiredKind - - return getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false), - Spec: Spec{ - Verbose: false, - ReplicaCount: 1, - StorageCapacity: "368Gi", - StorageClass: "testSC", - NodeSelector: map[string]string{}, - ClusterDns: "testDns", - Backups: map[string]*tree.Tree{backupName: bucketDesired}, - }, - }) -} - -func TestManaged_AdaptBucketBackup(t *testing.T) { - monitor := mntr.Monitor{} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "database") - - labels := map[string]string{ - "app.kubernetes.io/component": "backup", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - namespace := "testNs" - timestamp := "testTs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - backupName := "testBucket" - saJson := "testSA" - masterkey := "testMk" - version := "test" - - desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName) - - features := []string{backup.Normal} - bucket.SetBackup(k8sClient, namespace, labels, saJson) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second) - - query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{}) - assert.NoError(t, err) - - databases := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases, []string{}) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestManaged_AdaptBucketInstantBackup(t *testing.T) { - monitor := mntr.Monitor{} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "database") - labels := map[string]string{ - "app.kubernetes.io/component": "backup", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - namespace := "testNs" - timestamp := "testTs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - masterkey := "testMk" - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - saJson := "testSA" - backupName := "testBucket" - version := "test" - - features := []string{backup.Instant} - bucket.SetInstantBackup(k8sClient, namespace, backupName, labels, saJson) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second) - - desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName) - - query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{}) - assert.NoError(t, err) - - databases := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases, []string{}) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestManaged_AdaptBucketCleanAndRestore(t *testing.T) { - monitor := mntr.Monitor{} - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "database") - labels := map[string]string{ - "app.kubernetes.io/component": "backup", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "backup-serviceaccountjson", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "BucketBackup", - } - namespace := "testNs" - timestamp := "testTs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - version := "testVersion" - masterkey := "testMk" - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - saJson := "testSA" - backupName := "testBucket" - - features := []string{restore.Instant} - bucket.SetRestore(k8sClient, namespace, backupName, labels, saJson) - //SetClean(k8sClient, namespace, 1) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second).Times(1) - - desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName) - - query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{}) - assert.NoError(t, err) - - databases := []string{"test1", "test2"} - users := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases, users) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/adapt_test.go b/operator/database/kinds/databases/managed/adapt_test.go deleted file mode 100644 index 5b6a1a826c..0000000000 --- a/operator/database/kinds/databases/managed/adapt_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package managed - -import ( - "testing" - "time" - - "gopkg.in/yaml.v3" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - coremock "github.com/caos/zitadel/operator/database/kinds/databases/core/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - policy "k8s.io/api/policy/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func getDesiredTree(t *testing.T, masterkey string, desired interface{}) *tree.Tree { - secret.Masterkey = masterkey - - desiredTree := &tree.Tree{} - data, err := yaml.Marshal(desired) - assert.NoError(t, err) - assert.NoError(t, yaml.Unmarshal(data, desiredTree)) - - return desiredTree -} - -func TestManaged_Adapt1(t *testing.T) { - monitor := mntr.Monitor{} - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "database", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - - cockroachLabels := map[string]string{ - "app.kubernetes.io/component": "database", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb-budget", - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "testKind", - } - - cockroachSelectorLabels := map[string]string{ - "app.kubernetes.io/component": "database", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "database") - - namespace := "testNs" - timestamp := "testTs" - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - features := []string{"database"} - masterkey := "testMk" - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - queried := map[string]interface{}{} - version := "test" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false), - Spec: Spec{ - Verbose: false, - ReplicaCount: 1, - StorageCapacity: "368Gi", - StorageClass: "testSC", - NodeSelector: map[string]string{}, - ClusterDns: "testDns", - }, - }) - - unav := intstr.FromInt(1) - k8sClient.EXPECT().ApplyPodDisruptionBudget(&policy.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cockroachdb-budget", - Namespace: namespace, - Labels: cockroachLabels, - }, - Spec: policy.PodDisruptionBudgetSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: cockroachSelectorLabels, - }, - MaxUnavailable: &unav, - }, - }) - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - - k8sClient.EXPECT().ApplyService(gomock.Any()).Times(3) - k8sClient.EXPECT().ApplyServiceAccount(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyRole(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyClusterRole(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyRoleBinding(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyClusterRoleBinding(gomock.Any()).MinTimes(1).MaxTimes(1) - //statefulset - k8sClient.EXPECT().ApplyStatefulSet(gomock.Any(), gomock.Any()).MinTimes(1).MaxTimes(1) - //running for setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, false, 60*time.Second).MinTimes(1).MaxTimes(1) - //not ready for setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 1*time.Second).MinTimes(1).MaxTimes(1) - //ready after setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second).MinTimes(1).MaxTimes(1) - //client - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).MinTimes(1).MaxTimes(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().MinTimes(1).MaxTimes(1).Return(nil) - k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) - //node - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).MinTimes(1).MaxTimes(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).MinTimes(1).MaxTimes(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) - - query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{}) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestManaged_Adapt2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - timestamp := "testTs" - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "database2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd2", - "orbos.ch/selectable": "yes", - } - - cockroachLabels := map[string]string{ - "app.kubernetes.io/component": "database2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": "cockroachdb-budget", - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testVersion2", - "caos.ch/apiversion": "v1", - "caos.ch/kind": "testKind2", - } - - cockroachSelectorLabels := map[string]string{ - "app.kubernetes.io/component": "database2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": "cockroachdb", - "app.kubernetes.io/part-of": "testProd2", - "orbos.ch/selectable": "yes", - } - - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "testKind2", "v1"), "database2") - - nodeselector := map[string]string{"test2": "test2"} - var tolerations []corev1.Toleration - features := []string{"database"} - masterkey := "testMk2" - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - queried := map[string]interface{}{} - version := "test" - - desired := getDesiredTree(t, masterkey, &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false), - Spec: Spec{ - Verbose: false, - ReplicaCount: 1, - StorageCapacity: "368Gi", - StorageClass: "testSC", - NodeSelector: map[string]string{}, - ClusterDns: "testDns", - }, - }) - - unav := intstr.FromInt(1) - k8sClient.EXPECT().ApplyPodDisruptionBudget(&policy.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cockroachdb-budget", - Namespace: namespace, - Labels: cockroachLabels, - }, - Spec: policy.PodDisruptionBudgetSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: cockroachSelectorLabels, - }, - MaxUnavailable: &unav, - }, - }) - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - - k8sClient.EXPECT().ApplyService(gomock.Any()).Times(3) - k8sClient.EXPECT().ApplyServiceAccount(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyRole(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyClusterRole(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyRoleBinding(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplyClusterRoleBinding(gomock.Any()).MinTimes(1).MaxTimes(1) - //statefulset - k8sClient.EXPECT().ApplyStatefulSet(gomock.Any(), gomock.Any()).MinTimes(1).MaxTimes(1) - //running for setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, false, 60*time.Second).MinTimes(1).MaxTimes(1) - //not ready for setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 1*time.Second).MinTimes(1).MaxTimes(1) - //ready after setup - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second).MinTimes(1).MaxTimes(1) - //client - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).MinTimes(1).MaxTimes(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().MinTimes(1).MaxTimes(1).Return(nil) - k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) - //node - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).MinTimes(1).MaxTimes(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().MinTimes(1).MaxTimes(1).Return(nil) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).MinTimes(1).MaxTimes(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1) - k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) - - query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{}) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/certificate/adapt.go b/operator/database/kinds/databases/managed/certificate/adapt.go deleted file mode 100644 index 9ba4d55246..0000000000 --- a/operator/database/kinds/databases/managed/certificate/adapt.go +++ /dev/null @@ -1,91 +0,0 @@ -package certificate - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/client" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/node" -) - -var ( - nodeSecret = "cockroachdb.node" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - componentLabels *labels.Component, - clusterDns string, - generateNodeIfNotExists bool, -) ( - operator.QueryFunc, - operator.DestroyFunc, - func(user string) (operator.QueryFunc, error), - func(user string) (operator.DestroyFunc, error), - func(k8sClient kubernetes.ClientInt) ([]string, error), - error, -) { - cMonitor := monitor.WithField("type", "certificates") - - queryNode, destroyNode, err := node.AdaptFunc( - cMonitor, - namespace, - labels.MustForName(componentLabels, nodeSecret), - clusterDns, - generateNodeIfNotExists, - ) - if err != nil { - return nil, nil, nil, nil, nil, err - } - - queriers := []operator.QueryFunc{ - queryNode, - } - - destroyers := []operator.DestroyFunc{ - destroyNode, - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(cMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(cMonitor, destroyers), - func(user string) (operator.QueryFunc, error) { - query, _, err := client.AdaptFunc( - cMonitor, - namespace, - componentLabels, - ) - if err != nil { - return nil, err - } - queryClient := query(user) - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - _, err := queryNode(k8sClient, queried) - if err != nil { - return nil, err - } - - return queryClient(k8sClient, queried) - }, nil - }, - func(user string) (operator.DestroyFunc, error) { - _, destroy, err := client.AdaptFunc( - cMonitor, - namespace, - componentLabels, - ) - if err != nil { - return nil, err - } - - return destroy(user), nil - }, - func(k8sClient kubernetes.ClientInt) ([]string, error) { - return client.QueryCertificates(namespace, labels.DeriveComponentSelector(componentLabels, false), k8sClient) - }, - nil -} diff --git a/operator/database/kinds/databases/managed/certificate/adapt_test.go b/operator/database/kinds/databases/managed/certificate/adapt_test.go deleted file mode 100644 index 246beab21d..0000000000 --- a/operator/database/kinds/databases/managed/certificate/adapt_test.go +++ /dev/null @@ -1,305 +0,0 @@ -package certificate - -import ( - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - coremock "github.com/caos/zitadel/operator/database/kinds/databases/core/mock" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" -) - -const ( - caPem = `-----BEGIN CERTIFICATE----- -MIIE9TCCAt2gAwIBAgICB+MwDQYJKoZIhvcNAQELBQAwKzESMBAGA1UEChMJQ29j -a3JvYWNoMRUwEwYDVQQDEwxDb2Nrcm9hY2ggQ0EwHhcNMjAxMjAxMTAyMjA0WhcN -MzAxMjAxMTAyMjA0WjArMRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENv -Y2tyb2FjaCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOja5IXJ -GUY9sFgyvWkav+O74gzcv8y69uJzSOx0piOP+sfpZWVeGEjqO4JgdcS5NPMrT5Tb -aJ52CjiOdlHVTyR87i5JmOIvA2qA4dWQmSbX7AQ8r9ptYDe9xMn+qFegcbr4YxCz -K9mmbDZUhlLO7cz3QV6nvRxGFWbzffo8BXZnOUCAOyOHrbnPpLumnfZlL5BckdtY -pS7jAlUpKSMBTK4AHcmrouFsNKHqlUopYXeJFdg9g1F0DuCnVP9x7+XcUW8dAVut -Q7Jswy+++GAXs6mPVsYFLXUSYNyW+Bfl/jKwx0XTQx/6iyNpK0XtAzjBZFjXwmot -0mODkqnfE3BB4lXxZ5knomAQEGSScUhCUb9upbF4uJJF27xr/kIkwtWxMGpCXds0 -IxI+wNRCenhfFZEIQCzri0zn6WdN8b/gbv1BErNcccYwolPUv1oUgYbzowbQ5O2D -aLQPqO1VAZiZHLxb787bRywpCl33VZ1ptMHi2ogKjcsh4DQ9SsRj+rU/Tk5lyk7G -FHteyHcq12TGpz9/CQYMacl8yeRRHfNO3Rq0jFTYeD4+ZdVBPKeuTHyXGzy2T157 -pgqMFzwqxlNYPzpuz7xsZBExJzCtcomB8fMlsCJnxV/kuMTTsWsPrRc7hsqzBCq3 -plfYT8a7EBCVmJmDu+6mMVh+A9M2zZCqtV57AgMBAAGjIzAhMA4GA1UdDwEB/wQE -AwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQDRmkBYDk/F -lYTgMaL7yhRAowDR8mtOl06Oba/MCDDsmBvfOVIqY9Sa9sJtb78Uvecv9WAE4qpb -PNSaIvNmujmGQrBxtGwQdeHZvtXQ1lKAGBM+ukfz/NFU+6rwOdTuLgS5jTaiM4r1 -uMoIG6S5z/brWGHAw8Qv2Fq05dSLnevmPWK903V/RnwmCKT9as5Qpfkaie2PNory -euxVGeGolxzgbSps3ZJlDSSymQBl10iJYYdGIsgcw5FHcCdpS4AutdpQbIFuCGk2 -CHTcTTa4KMaVfRm/gKm1gh8UnuVDLBKQS8+1CHFYUnih8ozBNUyBo5r5L4BHJK/n -f0gnrYqaxtqPAyHkfo0PRc50HlAQRS/gW8ESv2PQmcSWlDggEzXt5MqFIYOfEXWE -gtC7Ct1P7gzIRxolYVsNSgBR62sJM1PUa39E5v0QJsmuM51txHuw/PGqkkBlEwx9 -4u3FFXD9Pslg/g1l50Ek5O3/TWMta4Q+NagDDaOdkb4LRQr522ySgGIinBw00Xr+ -Ics2L42rP1LQyaE7+BljDEwmGaT7mrl8QGZR9uv/9mbtk2+q7wAOQzcMSFFACfwx -KdKENmK0GpQZ6HaeDZO7wxGiAyFKhTNpd39XNOEhaKpWLSUxnZTLGlMIzvSyMGCj -PV3xm+Xg1Xvki7f/qC1djysMcaokoJzNdg== ------END CERTIFICATE----- -` - caPrivPem = `-----BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEA2Owc3IOljq3hkKO9q6jT1kFZp/+Y9dv/lTIbsMhV7gPrn2WS -Os2KQphcrB9DvGoZAxUh1aD8MUO7USIMhFodQEq7vfycDT16jrTnc1fSDDcfk3Ra -DvqZGcBkj0lc6w5LK3FNl2y6rA/26teGbyNaVXJfW01dKKy4E2or2+1+tUamyjiU -cvPzNWEoPPJT5HcadLTxZr/SKDvDXFyej4nKT9+j1pKmaqQrIrL4KXKq75LhU+kH -L4TG+kJ35isiv5OTpd2jG6ssz0i+ZEtX4hjIM6eCnZaiFT//33nSL3zl2LUjmyou -ks2FDuX9m90mg8UtcrpA/eVlwyg8nJ/d7/Yn3ZjuHVOgzE8YuQXauJ16HuLcFgEW -WQg1uwhOhrc5b0YJndZbJ2Re4qfaBoC5fODRXoUPvqG9k9kNp98xtclNCIyW8EpA -Su8QmK42ksOJox+OQamHzatrGppgIK77TY3ZFcBHETHClabgsfjv/1GNXXAexJI4 -Cjntnou+yoc+LUj87WJfD3ERGgm0nDfnE7uZ7kccO5Lj/oajeO+Q+QJaLZ4I2jz+ -a05k16naGGT29AnM+iwBqqoTODr4Z7905niZc6+fEOPml1V7wSuJs2eE4jOa3ixX -5tnruw74rN82Zfrkg6kWPOEfBBXzSotRiHv+BAV2tFbnC55ItnHn1ZE68V0CAwEA -AQKCAgEAssWsZ4PLXpIo8qYve5hQtSP4er7oVb8wnMnGDmSchOMQPbZc1D9uscGV -pnjBvzcFVAgHcWMSVJuIda4E+NK3hrPQlBvqk/LV3WRz1xhKUKzhRgm+6tdWc+We -OoRwonuOMchX9PKzyXgCu7pR3agaG499zOYuX4Yw0jdO3BqXsVf/v2rv1Oj9yEFB -AzGHOCN8VzCEPnTaAzR1pdnjB1K8vCUIhp8nrX2M2zT51lbdT0ISl6/VrzDTN46t -97AXHCHIrgrCENx6un4uAsQhMoHQBNoJiEyLWc371zYzpdVeK8HlDUyvQ2dDQGsF -Hn4c7r4C3aloRJbYzgSMJ1yNcOTCJpciQsq1VmCQFOHfbum2ejquXJ7BbeRGeHdM -145epckL+hbECTCpSs0Z5t90NdfoJspvr+3sOEt6h3DMUGjvobrf/s3KiRY5hHdc -x86Htx3QgWNCG6a+ga7h7s3t+4ZtoPPWn+vlAoxD/2eCzsDgE/XLDmC2T4yS8UOb -LIb4UN7wl2sNM8zhm4BfoiKfjGu4dPZIlsPP+ZKRby1O4ogHHoPREBTH1VSEplVM -fA/KSITV+rUfO3T/qXIFZ4/Wa5YZoULiMCOJOWNgXQzWvTf7Qr31LhhfXd+uIw30 -LDtjdkpT43zlKxRosQFLiV7q3fVbvKPVQfxzBz7M1Gl74IllpmECggEBAOnAimKl -w/9mcMkEd2L2ZzDI+57W8DU6grUUILZfjJG+uvOiMmIA5M1wzsVHil3ihZthrJ5A -UUAKG97JgwjpIAliAzgtPZY2AK/bJz7Hht1EwewrV+RyHM+dMv6em2OA+XUjFSPX -VsecFDaUQebkypw236KdA4jgRG6hr4xObdXgTN6RFCv1mI1EijZ/YbKgPgTJaPI4 -b2N5QokYFygUCwRxKIt7/Z4hQs9LbdW680NcXtPRPnS1SmwYJbi7wTX+o5f6nfNV -YvojborjXwNrZe0p+FfaEuD44wf6kNlRGfcKXoaAncXV/M5/oXf1dktKP630eq9g -0MAKFYJ6MAUheakCggEBAO2Rgfy/tEydBuP9BIfC84BXk8EwnRJ0ZfmXv77HFj3F -VT5QNU97I5gZJOFkL7OO8bL0/WljlqeBEht0DmHNmOt5Pyew4LRLpfeN6rClZgRN -V4wqKXjoZAIYa9khQcwwFNER1RdI+PkuusJtrvY6CbwwG9LbBq2NR4C1YSgaQnhV -NqdXK5dwrYEky6lI31sDD4BYeiJVKlkkNCQAVOC+04Mrsa9F0NG7TKXzji5hU8l5 -x8squjvJ6vmobhmsRTL1LMpafUrt5pHL9jcWIZYxJJo9mB0zxJKcsLI8IOg2QPoj -tQ395FZ2YtjNzZa1CYeUOUiaQu+uvztfE36AdW/vUpUCggEAMV7bW66LURw/4hUx -ahOFBAbPLmNTZMqw5LIVnq9br0TLk73ESnLJ4KJc6coMbXv0oDbnEJ2hC5eW/10s -cetbOuAasfjMMzfAuWPeTCI0V/O3ybv12mhHsYoQRTsWstOA3L7GLkXDLHHIyyZR -LQVRzeDBJ0Vmg7hqe7tmqom+JRg05CVcT1SWHfBGCPCqn+G8d6Jaqh5FWIs6BF60 -NWDWWt/TonJTxNxdkg7qaeQMkUOnO7HMMTZBO8d14Ci3zEG2J9llFwoH17E4Hdmc -Lcq3QnpE27lRl3a57Ot9QIkipMzp3hq4OBrURIEsh3uuuoQ6IvGqH/Sg4o6+sEpC -bjL90QKCAQBDc/0kdooK9sruEPkoUwIwfq1FPThb9RC/PYcD9CMshssdVkjMuHny -xbDjDj89DGk0FrudINm11b/+a4Vp36Z7tYFpE5+5kYEeOP1aCpxcvFkPQyljWxiK -P8TfccHs5/oBIr8OTXnjxpDgg6QZ5YC+HirIQ8gxntuef+GGMW6OHCPYf7ew2B1r -fbcV6csBXG0aVATZmrTbepwTXMS8y3Hi3JUm3vvbkQLCW9US9i+EFT/VP9yA/WPq -Xxhj0bYUMej1y5unmsTMwMy392Cx9GIgKTz3jatStYq2ELyHMmBgpaLSxjP/GL4Y -MNce42hBRqS9KI+43jUN9oDiejbeAWXBAoIBACZKnS6EppNDSdos0f32J5TxEUxv -lF9AuVXEAPDR/m3+PlSRzrlf7uowdHTfsemHMSduL8weLNhduprwz4TmW9Fo6fSF -UePLNbXcMX3omAk+AKKOiexLG0fCXGW2zr4nHZJzTbK2+La3yLeUcoPu1puNpLiq -LVj2bH3zKWVRA9/ovuN6V5w18ojjdqOw4bw5qXcdZhoWLxI8Q9Oqua24f/dnRpuI -I8mRtPQ3+vuOKbTT+/80eAUpSfEKwAg1Mjgury9q1/B4Ib6hAGzpJuXxG7xQjnsJ -EFcN1kvdg5WGK41+fYMdexPaLamjhDGN0e1vxJfAukWIAsBMwp8wfEWZvzA= ------END RSA PRIVATE KEY----- -` -) - -func TestCertificate_AdaptWithCA(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - ca, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPriv, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().Times(1).Return(ca) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(caPriv) - dbCurrent.EXPECT().SetCertificate(ca).Times(1) - dbCurrent.EXPECT().SetCertificateKey(caPriv).Times(1) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, _, _, _, err := AdaptFunc(monitor, namespace, componentLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestNode_AdaptWithoutCA(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().Times(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(nil) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).Times(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).Times(1) - k8sClient.EXPECT().ApplySecret(gomock.Any()).Times(1).Return(nil) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, _, _, _, err := AdaptFunc(monitor, namespace, componentLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestNode_AdaptAlreadyExisting(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - caCertKey := "ca.crt" - caPrivKeyKey := "ca.key" - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{{ - ObjectMeta: metav1.ObjectMeta{}, - Data: map[string][]byte{ - caCertKey: []byte(caPem), - caPrivKeyKey: []byte(caPrivPem), - }, - Type: "Opaque", - }}, - } - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).Times(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).Times(1) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, _, _, _, err := AdaptFunc(monitor, namespace, componentLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestNode_AdaptCreateUser(t *testing.T) { - monitor := mntr.Monitor{} - clusterDns := "testDns" - namespace := "testNs" - user := "test" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "cockroachdb.node", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - ca, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPriv, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - caCertKey := "ca.crt" - caPrivKeyKey := "ca.key" - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{{ - ObjectMeta: metav1.ObjectMeta{}, - Data: map[string][]byte{ - caCertKey: []byte(caPem), - caPrivKeyKey: []byte(caPrivPem), - }, - Type: "Opaque", - }}, - } - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - - dbCurrent.EXPECT().GetCertificate().Times(1).Return(ca) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(caPriv) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).Times(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).Times(1) - k8sClient.EXPECT().ApplySecret(gomock.Any()) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - core.SetQueriedForDatabase(queried, current) - - _, _, createUser, _, _, err := AdaptFunc(monitor, namespace, componentLabels, clusterDns, true) - assert.NoError(t, err) - query, err := createUser(user) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/certificate/certificates/certificates.go b/operator/database/kinds/databases/managed/certificate/certificates/certificates.go deleted file mode 100644 index 5e3fa3fe6d..0000000000 --- a/operator/database/kinds/databases/managed/certificate/certificates/certificates.go +++ /dev/null @@ -1,111 +0,0 @@ -package certificates - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "math/big" - "net" - "time" -) - -func NewCA() (*rsa.PrivateKey, []byte, error) { - ca := &x509.Certificate{ - SerialNumber: big.NewInt(2019), - Subject: pkix.Name{ - Organization: []string{"Cockroach"}, - CommonName: "Cockroach CA", - }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - IsCA: true, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign, - BasicConstraintsValid: true, - } - - caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - return nil, nil, err - } - - caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey) - if err != nil { - return nil, nil, err - } - - return caPrivKey, caBytes, nil -} - -func NewClient(caPrivKey *rsa.PrivateKey, ca []byte, user string) (*rsa.PrivateKey, []byte, error) { - cert := &x509.Certificate{ - SerialNumber: big.NewInt(1658), - Subject: pkix.Name{ - Organization: []string{"Cockroach"}, - CommonName: user, - }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - } - - certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - return nil, nil, err - } - - caCert, err := x509.ParseCertificate(ca) - if err != nil { - return nil, nil, err - } - - certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, &certPrivKey.PublicKey, caPrivKey) - if err != nil { - return nil, nil, err - } - - return certPrivKey, certBytes, nil -} - -func NewNode(caPrivKey *rsa.PrivateKey, ca []byte, namespace string, clusterDns string) (*rsa.PrivateKey, []byte, error) { - cert := &x509.Certificate{ - SerialNumber: big.NewInt(1658), - Subject: pkix.Name{ - Organization: []string{"Cockroach"}, - CommonName: "node", - }, - IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1)}, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - DNSNames: []string{ - "localhost", - "cockroachdb-public", - "cockroachdb-public.default", - "cockroachdb-public." + namespace, - "cockroachdb-public." + namespace + ".svc." + clusterDns, - "*.cockroachdb", - "*.cockroachdb." + namespace, - "*.cockroachdb." + namespace + ".svc." + clusterDns, - }, - } - - certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - return nil, nil, err - } - - caCert, err := x509.ParseCertificate(ca) - if err != nil { - return nil, nil, err - } - - certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, &certPrivKey.PublicKey, caPrivKey) - if err != nil { - return nil, nil, err - } - - return certPrivKey, certBytes, nil -} diff --git a/operator/database/kinds/databases/managed/certificate/certificates/certificates_test.go b/operator/database/kinds/databases/managed/certificate/certificates/certificates_test.go deleted file mode 100644 index 83f88e90fb..0000000000 --- a/operator/database/kinds/databases/managed/certificate/certificates/certificates_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package certificates - -import ( - "crypto/x509" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestCertificates_CAE(t *testing.T) { - priv, rootCa, err := NewCA() - assert.NoError(t, err) - assert.NotNil(t, priv) - - pemCa, err := pem.EncodeCertificate(rootCa) - pemkey, err := pem.EncodeKey(priv) - assert.NotNil(t, pemCa) - assert.NotNil(t, pemkey) - - _, err = x509.ParseCertificate(rootCa) - assert.NoError(t, err) -} - -func TestCertificates_CA(t *testing.T) { - _, rootCa, err := NewCA() - assert.NoError(t, err) - - _, err = x509.ParseCertificate(rootCa) - assert.NoError(t, err) -} - -func TestCertificates_Chain(t *testing.T) { - rootKey, rootCert, err := NewCA() - assert.NoError(t, err) - rootPem, err := pem.EncodeCertificate(rootCert) - assert.NoError(t, err) - - roots := x509.NewCertPool() - ok := roots.AppendCertsFromPEM(rootPem) - assert.Equal(t, ok, true) - - _, clientCert, err := NewClient(rootKey, rootCert, "test") - - cert, err := x509.ParseCertificate(clientCert) - assert.NoError(t, err) - - opts := x509.VerifyOptions{ - Roots: roots, - KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - } - - _, err = cert.Verify(opts) - assert.NoError(t, err) -} diff --git a/operator/database/kinds/databases/managed/certificate/client/adapt.go b/operator/database/kinds/databases/managed/certificate/client/adapt.go deleted file mode 100644 index 84e5a25577..0000000000 --- a/operator/database/kinds/databases/managed/certificate/client/adapt.go +++ /dev/null @@ -1,101 +0,0 @@ -package client - -import ( - "errors" - "github.com/caos/zitadel/operator" - "strings" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/secret" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/certificates" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" -) - -const ( - clientSecretPrefix = "cockroachdb.client." - caCertKey = "ca.crt" - clientCertKeyPrefix = "client." - clientCertKeySuffix = ".crt" - clientPrivKeyKeyPrefix = "client." - clientPrivKeyKeySuffix = ".key" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - componentLabels *labels.Component, -) ( - func(client string) operator.QueryFunc, - func(client string) operator.DestroyFunc, - error, -) { - - return func(client string) operator.QueryFunc { - clientSecret := clientSecretPrefix + client - nameLabels := labels.MustForName(componentLabels, strings.ReplaceAll(clientSecret, "_", "-")) - clientCertKey := clientCertKeyPrefix + client + clientCertKeySuffix - clientPrivKeyKey := clientPrivKeyKeyPrefix + client + clientPrivKeyKeySuffix - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - queriers := make([]operator.QueryFunc, 0) - - currentDB, err := core.ParseQueriedForDatabase(queried) - if err != nil { - return nil, err - } - - caCert := currentDB.GetCertificate() - caKey := currentDB.GetCertificateKey() - if caKey == nil || caCert == nil || len(caCert) == 0 { - return nil, errors.New("no ca-certificate found") - } - - clientPrivKey, clientCert, err := certificates.NewClient(caKey, caCert, client) - if err != nil { - return nil, err - } - - pemClientPrivKey, err := pem.EncodeKey(clientPrivKey) - if err != nil { - return nil, err - } - - pemClientCert, err := pem.EncodeCertificate(clientCert) - if err != nil { - return nil, err - } - - pemCaCert, err := pem.EncodeCertificate(caCert) - if err != nil { - return nil, err - } - - clientSecretData := map[string]string{ - caCertKey: string(pemCaCert), - clientPrivKeyKey: string(pemClientPrivKey), - clientCertKey: string(pemClientCert), - } - - queryClientSecret, err := secret.AdaptFuncToEnsure(namespace, labels.AsSelectable(nameLabels), clientSecretData) - if err != nil { - return nil, err - } - queriers = append(queriers, operator.ResourceQueryToZitadelQuery(queryClientSecret)) - - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - } - }, func(client string) operator.DestroyFunc { - clientSecret := clientSecretPrefix + client - - destroy, err := secret.AdaptFuncToDestroy(namespace, clientSecret) - if err != nil { - return nil - } - return operator.ResourceDestroyToZitadelDestroy(destroy) - }, - nil -} diff --git a/operator/database/kinds/databases/managed/certificate/client/adapt_test.go b/operator/database/kinds/databases/managed/certificate/client/adapt_test.go deleted file mode 100644 index 794c7dc3a8..0000000000 --- a/operator/database/kinds/databases/managed/certificate/client/adapt_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package client - -import ( - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - coremock "github.com/caos/zitadel/operator/database/kinds/databases/core/mock" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -const ( - caPem = `-----BEGIN CERTIFICATE----- -MIIE9TCCAt2gAwIBAgICB+MwDQYJKoZIhvcNAQELBQAwKzESMBAGA1UEChMJQ29j -a3JvYWNoMRUwEwYDVQQDEwxDb2Nrcm9hY2ggQ0EwHhcNMjAxMjAxMTAyMjA0WhcN -MzAxMjAxMTAyMjA0WjArMRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENv -Y2tyb2FjaCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOja5IXJ -GUY9sFgyvWkav+O74gzcv8y69uJzSOx0piOP+sfpZWVeGEjqO4JgdcS5NPMrT5Tb -aJ52CjiOdlHVTyR87i5JmOIvA2qA4dWQmSbX7AQ8r9ptYDe9xMn+qFegcbr4YxCz -K9mmbDZUhlLO7cz3QV6nvRxGFWbzffo8BXZnOUCAOyOHrbnPpLumnfZlL5BckdtY -pS7jAlUpKSMBTK4AHcmrouFsNKHqlUopYXeJFdg9g1F0DuCnVP9x7+XcUW8dAVut -Q7Jswy+++GAXs6mPVsYFLXUSYNyW+Bfl/jKwx0XTQx/6iyNpK0XtAzjBZFjXwmot -0mODkqnfE3BB4lXxZ5knomAQEGSScUhCUb9upbF4uJJF27xr/kIkwtWxMGpCXds0 -IxI+wNRCenhfFZEIQCzri0zn6WdN8b/gbv1BErNcccYwolPUv1oUgYbzowbQ5O2D -aLQPqO1VAZiZHLxb787bRywpCl33VZ1ptMHi2ogKjcsh4DQ9SsRj+rU/Tk5lyk7G -FHteyHcq12TGpz9/CQYMacl8yeRRHfNO3Rq0jFTYeD4+ZdVBPKeuTHyXGzy2T157 -pgqMFzwqxlNYPzpuz7xsZBExJzCtcomB8fMlsCJnxV/kuMTTsWsPrRc7hsqzBCq3 -plfYT8a7EBCVmJmDu+6mMVh+A9M2zZCqtV57AgMBAAGjIzAhMA4GA1UdDwEB/wQE -AwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQDRmkBYDk/F -lYTgMaL7yhRAowDR8mtOl06Oba/MCDDsmBvfOVIqY9Sa9sJtb78Uvecv9WAE4qpb -PNSaIvNmujmGQrBxtGwQdeHZvtXQ1lKAGBM+ukfz/NFU+6rwOdTuLgS5jTaiM4r1 -uMoIG6S5z/brWGHAw8Qv2Fq05dSLnevmPWK903V/RnwmCKT9as5Qpfkaie2PNory -euxVGeGolxzgbSps3ZJlDSSymQBl10iJYYdGIsgcw5FHcCdpS4AutdpQbIFuCGk2 -CHTcTTa4KMaVfRm/gKm1gh8UnuVDLBKQS8+1CHFYUnih8ozBNUyBo5r5L4BHJK/n -f0gnrYqaxtqPAyHkfo0PRc50HlAQRS/gW8ESv2PQmcSWlDggEzXt5MqFIYOfEXWE -gtC7Ct1P7gzIRxolYVsNSgBR62sJM1PUa39E5v0QJsmuM51txHuw/PGqkkBlEwx9 -4u3FFXD9Pslg/g1l50Ek5O3/TWMta4Q+NagDDaOdkb4LRQr522ySgGIinBw00Xr+ -Ics2L42rP1LQyaE7+BljDEwmGaT7mrl8QGZR9uv/9mbtk2+q7wAOQzcMSFFACfwx -KdKENmK0GpQZ6HaeDZO7wxGiAyFKhTNpd39XNOEhaKpWLSUxnZTLGlMIzvSyMGCj -PV3xm+Xg1Xvki7f/qC1djysMcaokoJzNdg== ------END CERTIFICATE----- -` - caPrivPem = `-----BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEA2Owc3IOljq3hkKO9q6jT1kFZp/+Y9dv/lTIbsMhV7gPrn2WS -Os2KQphcrB9DvGoZAxUh1aD8MUO7USIMhFodQEq7vfycDT16jrTnc1fSDDcfk3Ra -DvqZGcBkj0lc6w5LK3FNl2y6rA/26teGbyNaVXJfW01dKKy4E2or2+1+tUamyjiU -cvPzNWEoPPJT5HcadLTxZr/SKDvDXFyej4nKT9+j1pKmaqQrIrL4KXKq75LhU+kH -L4TG+kJ35isiv5OTpd2jG6ssz0i+ZEtX4hjIM6eCnZaiFT//33nSL3zl2LUjmyou -ks2FDuX9m90mg8UtcrpA/eVlwyg8nJ/d7/Yn3ZjuHVOgzE8YuQXauJ16HuLcFgEW -WQg1uwhOhrc5b0YJndZbJ2Re4qfaBoC5fODRXoUPvqG9k9kNp98xtclNCIyW8EpA -Su8QmK42ksOJox+OQamHzatrGppgIK77TY3ZFcBHETHClabgsfjv/1GNXXAexJI4 -Cjntnou+yoc+LUj87WJfD3ERGgm0nDfnE7uZ7kccO5Lj/oajeO+Q+QJaLZ4I2jz+ -a05k16naGGT29AnM+iwBqqoTODr4Z7905niZc6+fEOPml1V7wSuJs2eE4jOa3ixX -5tnruw74rN82Zfrkg6kWPOEfBBXzSotRiHv+BAV2tFbnC55ItnHn1ZE68V0CAwEA -AQKCAgEAssWsZ4PLXpIo8qYve5hQtSP4er7oVb8wnMnGDmSchOMQPbZc1D9uscGV -pnjBvzcFVAgHcWMSVJuIda4E+NK3hrPQlBvqk/LV3WRz1xhKUKzhRgm+6tdWc+We -OoRwonuOMchX9PKzyXgCu7pR3agaG499zOYuX4Yw0jdO3BqXsVf/v2rv1Oj9yEFB -AzGHOCN8VzCEPnTaAzR1pdnjB1K8vCUIhp8nrX2M2zT51lbdT0ISl6/VrzDTN46t -97AXHCHIrgrCENx6un4uAsQhMoHQBNoJiEyLWc371zYzpdVeK8HlDUyvQ2dDQGsF -Hn4c7r4C3aloRJbYzgSMJ1yNcOTCJpciQsq1VmCQFOHfbum2ejquXJ7BbeRGeHdM -145epckL+hbECTCpSs0Z5t90NdfoJspvr+3sOEt6h3DMUGjvobrf/s3KiRY5hHdc -x86Htx3QgWNCG6a+ga7h7s3t+4ZtoPPWn+vlAoxD/2eCzsDgE/XLDmC2T4yS8UOb -LIb4UN7wl2sNM8zhm4BfoiKfjGu4dPZIlsPP+ZKRby1O4ogHHoPREBTH1VSEplVM -fA/KSITV+rUfO3T/qXIFZ4/Wa5YZoULiMCOJOWNgXQzWvTf7Qr31LhhfXd+uIw30 -LDtjdkpT43zlKxRosQFLiV7q3fVbvKPVQfxzBz7M1Gl74IllpmECggEBAOnAimKl -w/9mcMkEd2L2ZzDI+57W8DU6grUUILZfjJG+uvOiMmIA5M1wzsVHil3ihZthrJ5A -UUAKG97JgwjpIAliAzgtPZY2AK/bJz7Hht1EwewrV+RyHM+dMv6em2OA+XUjFSPX -VsecFDaUQebkypw236KdA4jgRG6hr4xObdXgTN6RFCv1mI1EijZ/YbKgPgTJaPI4 -b2N5QokYFygUCwRxKIt7/Z4hQs9LbdW680NcXtPRPnS1SmwYJbi7wTX+o5f6nfNV -YvojborjXwNrZe0p+FfaEuD44wf6kNlRGfcKXoaAncXV/M5/oXf1dktKP630eq9g -0MAKFYJ6MAUheakCggEBAO2Rgfy/tEydBuP9BIfC84BXk8EwnRJ0ZfmXv77HFj3F -VT5QNU97I5gZJOFkL7OO8bL0/WljlqeBEht0DmHNmOt5Pyew4LRLpfeN6rClZgRN -V4wqKXjoZAIYa9khQcwwFNER1RdI+PkuusJtrvY6CbwwG9LbBq2NR4C1YSgaQnhV -NqdXK5dwrYEky6lI31sDD4BYeiJVKlkkNCQAVOC+04Mrsa9F0NG7TKXzji5hU8l5 -x8squjvJ6vmobhmsRTL1LMpafUrt5pHL9jcWIZYxJJo9mB0zxJKcsLI8IOg2QPoj -tQ395FZ2YtjNzZa1CYeUOUiaQu+uvztfE36AdW/vUpUCggEAMV7bW66LURw/4hUx -ahOFBAbPLmNTZMqw5LIVnq9br0TLk73ESnLJ4KJc6coMbXv0oDbnEJ2hC5eW/10s -cetbOuAasfjMMzfAuWPeTCI0V/O3ybv12mhHsYoQRTsWstOA3L7GLkXDLHHIyyZR -LQVRzeDBJ0Vmg7hqe7tmqom+JRg05CVcT1SWHfBGCPCqn+G8d6Jaqh5FWIs6BF60 -NWDWWt/TonJTxNxdkg7qaeQMkUOnO7HMMTZBO8d14Ci3zEG2J9llFwoH17E4Hdmc -Lcq3QnpE27lRl3a57Ot9QIkipMzp3hq4OBrURIEsh3uuuoQ6IvGqH/Sg4o6+sEpC -bjL90QKCAQBDc/0kdooK9sruEPkoUwIwfq1FPThb9RC/PYcD9CMshssdVkjMuHny -xbDjDj89DGk0FrudINm11b/+a4Vp36Z7tYFpE5+5kYEeOP1aCpxcvFkPQyljWxiK -P8TfccHs5/oBIr8OTXnjxpDgg6QZ5YC+HirIQ8gxntuef+GGMW6OHCPYf7ew2B1r -fbcV6csBXG0aVATZmrTbepwTXMS8y3Hi3JUm3vvbkQLCW9US9i+EFT/VP9yA/WPq -Xxhj0bYUMej1y5unmsTMwMy392Cx9GIgKTz3jatStYq2ELyHMmBgpaLSxjP/GL4Y -MNce42hBRqS9KI+43jUN9oDiejbeAWXBAoIBACZKnS6EppNDSdos0f32J5TxEUxv -lF9AuVXEAPDR/m3+PlSRzrlf7uowdHTfsemHMSduL8weLNhduprwz4TmW9Fo6fSF -UePLNbXcMX3omAk+AKKOiexLG0fCXGW2zr4nHZJzTbK2+La3yLeUcoPu1puNpLiq -LVj2bH3zKWVRA9/ovuN6V5w18ojjdqOw4bw5qXcdZhoWLxI8Q9Oqua24f/dnRpuI -I8mRtPQ3+vuOKbTT+/80eAUpSfEKwAg1Mjgury9q1/B4Ib6hAGzpJuXxG7xQjnsJ -EFcN1kvdg5WGK41+fYMdexPaLamjhDGN0e1vxJfAukWIAsBMwp8wfEWZvzA= ------END RSA PRIVATE KEY----- -` -) - -func TestClient_Adapt1(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - user := "test" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - ca, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPriv, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - dbCurrent.EXPECT().GetCertificate().Times(1).Return(ca) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(caPriv) - k8sClient.EXPECT().ApplySecret(gomock.Any()) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - core.SetQueriedForDatabase(queried, current) - - createUser, _, err := AdaptFunc(monitor, namespace, componentLabels) - assert.NoError(t, err) - query := createUser(user) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestClient_Adapt2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs2" - user := "test2" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb") - - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - ca, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPriv, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - dbCurrent.EXPECT().GetCertificate().Times(1).Return(ca) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(caPriv) - k8sClient.EXPECT().ApplySecret(gomock.Any()) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - core.SetQueriedForDatabase(queried, current) - - createUser, _, err := AdaptFunc(monitor, namespace, componentLabels) - assert.NoError(t, err) - query := createUser(user) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/certificate/client/query.go b/operator/database/kinds/databases/managed/certificate/client/query.go deleted file mode 100644 index 33e89e79b3..0000000000 --- a/operator/database/kinds/databases/managed/certificate/client/query.go +++ /dev/null @@ -1,32 +0,0 @@ -package client - -import ( - "strings" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/pkg/kubernetes" -) - -func QueryCertificates( - namespace string, - selector *labels.Selector, - k8sClient kubernetes.ClientInt, -) ( - []string, - error, -) { - - list, err := k8sClient.ListSecrets(namespace, labels.MustK8sMap(selector)) - if err != nil { - return nil, err - } - certs := []string{} - for _, secret := range list.Items { - if strings.HasPrefix(secret.Name, clientSecretPrefix) { - certs = append(certs, strings.TrimPrefix(secret.Name, clientSecretPrefix)) - } - } - - return certs, nil -} diff --git a/operator/database/kinds/databases/managed/certificate/client/query_test.go b/operator/database/kinds/databases/managed/certificate/client/query_test.go deleted file mode 100644 index e9d6ea9c14..0000000000 --- a/operator/database/kinds/databases/managed/certificate/client/query_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package client - -import ( - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" -) - -func TestClient_Query0(t *testing.T) { - namespace := "testNs" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "testComponent") - clientLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - - k8sClient.EXPECT().ListSecrets(namespace, clientLabels).Times(1).Return(secretList, nil) - - users, err := QueryCertificates(namespace, labels.DeriveComponentSelector(componentLabels, false), k8sClient) - assert.NoError(t, err) - assert.Equal(t, users, []string{}) -} - -func TestClient_Query(t *testing.T) { - namespace := "testNs" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "testComponent") - clientLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{{ - ObjectMeta: metav1.ObjectMeta{ - Name: clientSecretPrefix + "test", - }, - Data: map[string][]byte{}, - Type: "Opaque", - }}, - } - - k8sClient.EXPECT().ListSecrets(namespace, clientLabels).Times(1).Return(secretList, nil) - - users, err := QueryCertificates(namespace, labels.DeriveComponentSelector(componentLabels, false), k8sClient) - assert.NoError(t, err) - assert.Contains(t, users, "test") -} - -func TestClient_Query2(t *testing.T) { - namespace := "testNs" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "testKind", "v0"), "testComponent") - clientLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{{ - ObjectMeta: metav1.ObjectMeta{ - Name: clientSecretPrefix + "test1", - }, - Data: map[string][]byte{}, - Type: "Opaque", - }, { - ObjectMeta: metav1.ObjectMeta{ - Name: clientSecretPrefix + "test2", - }, - Data: map[string][]byte{}, - Type: "Opaque", - }}, - } - - k8sClient.EXPECT().ListSecrets(namespace, clientLabels).Times(1).Return(secretList, nil) - - users, err := QueryCertificates(namespace, labels.DeriveComponentSelector(componentLabels, false), k8sClient) - assert.NoError(t, err) - assert.Equal(t, users, []string{"test1", "test2"}) -} diff --git a/operator/database/kinds/databases/managed/certificate/current.go b/operator/database/kinds/databases/managed/certificate/current.go deleted file mode 100644 index 5c836e8149..0000000000 --- a/operator/database/kinds/databases/managed/certificate/current.go +++ /dev/null @@ -1,10 +0,0 @@ -package certificate - -import ( - "crypto/rsa" -) - -type Current struct { - CertificateKey *rsa.PrivateKey - Certificate []byte -} diff --git a/operator/database/kinds/databases/managed/certificate/node/adapt.go b/operator/database/kinds/databases/managed/certificate/node/adapt.go deleted file mode 100644 index 7cc2b8f5b4..0000000000 --- a/operator/database/kinds/databases/managed/certificate/node/adapt.go +++ /dev/null @@ -1,150 +0,0 @@ -package node - -import ( - "crypto/rsa" - "errors" - "github.com/caos/zitadel/operator" - "reflect" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/secret" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/certificates" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" -) - -const ( - caCertKey = "ca.crt" - caPrivKeyKey = "ca.key" - nodeCertKey = "node.crt" - nodePrivKeyKey = "node.key" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - nameLabels *labels.Name, - clusterDns string, - generateIfNotExists bool, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - - caPrivKey := new(rsa.PrivateKey) - caCert := make([]byte, 0) - nodeSecretSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - queriers := make([]operator.QueryFunc, 0) - - currentDB, err := core.ParseQueriedForDatabase(queried) - if err != nil { - return nil, err - } - - allNodeSecrets, err := k8sClient.ListSecrets(namespace, nodeSecretSelector) - if err != nil { - return nil, err - } - - if len(allNodeSecrets.Items) == 0 { - - if !generateIfNotExists { - return nil, errors.New("node secret not found") - } - - emptyCert := true - emptyKey := true - if currentCaCert := currentDB.GetCertificate(); currentCaCert != nil && len(currentCaCert) != 0 { - emptyCert = false - caCert = currentCaCert - } - if currentCaCertKey := currentDB.GetCertificateKey(); currentCaCertKey != nil && !reflect.DeepEqual(currentCaCertKey, &rsa.PrivateKey{}) { - emptyKey = false - caPrivKey = currentCaCertKey - } - - if emptyCert || emptyKey { - caPrivKeyInternal, caCertInternal, err := certificates.NewCA() - if err != nil { - return nil, err - } - caPrivKey = caPrivKeyInternal - caCert = caCertInternal - - nodePrivKey, nodeCert, err := certificates.NewNode(caPrivKey, caCert, namespace, clusterDns) - if err != nil { - return nil, err - } - - pemNodePrivKey, err := pem.EncodeKey(nodePrivKey) - if err != nil { - return nil, err - } - pemCaPrivKey, err := pem.EncodeKey(caPrivKey) - if err != nil { - return nil, err - } - - pemCaCert, err := pem.EncodeCertificate(caCert) - if err != nil { - return nil, err - } - - pemNodeCert, err := pem.EncodeCertificate(nodeCert) - if err != nil { - return nil, err - } - - nodeSecretData := map[string]string{ - caPrivKeyKey: string(pemCaPrivKey), - caCertKey: string(pemCaCert), - nodePrivKeyKey: string(pemNodePrivKey), - nodeCertKey: string(pemNodeCert), - } - queryNodeSecret, err := secret.AdaptFuncToEnsure(namespace, labels.AsSelectable(nameLabels), nodeSecretData) - if err != nil { - return nil, err - } - queriers = append(queriers, operator.ResourceQueryToZitadelQuery(queryNodeSecret)) - } - } else { - key, err := pem.DecodeKey(allNodeSecrets.Items[0].Data[caPrivKeyKey]) - if err != nil { - return nil, err - } - caPrivKey = key - - cert, err := pem.DecodeCertificate(allNodeSecrets.Items[0].Data[caCertKey]) - if err != nil { - return nil, err - } - caCert = cert - } - - currentDB.SetCertificate(caCert) - currentDB.SetCertificateKey(caPrivKey) - - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, func(k8sClient kubernetes.ClientInt) error { - allNodeSecrets, err := k8sClient.ListSecrets(namespace, nodeSecretSelector) - if err != nil { - return err - } - for _, deleteSecret := range allNodeSecrets.Items { - destroyer, err := secret.AdaptFuncToDestroy(namespace, deleteSecret.Name) - if err != nil { - return err - } - if err := destroyer(k8sClient); err != nil { - return err - } - } - return nil - }, nil -} diff --git a/operator/database/kinds/databases/managed/certificate/node/adapt_test.go b/operator/database/kinds/databases/managed/certificate/node/adapt_test.go deleted file mode 100644 index d43d5673b7..0000000000 --- a/operator/database/kinds/databases/managed/certificate/node/adapt_test.go +++ /dev/null @@ -1,245 +0,0 @@ -package node - -import ( - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/database/kinds/databases/core" - coremock "github.com/caos/zitadel/operator/database/kinds/databases/core/mock" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate/pem" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" -) - -const ( - caPem = `-----BEGIN CERTIFICATE----- -MIIE9TCCAt2gAwIBAgICB+MwDQYJKoZIhvcNAQELBQAwKzESMBAGA1UEChMJQ29j -a3JvYWNoMRUwEwYDVQQDEwxDb2Nrcm9hY2ggQ0EwHhcNMjAxMjAxMTAyMjA0WhcN -MzAxMjAxMTAyMjA0WjArMRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENv -Y2tyb2FjaCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOja5IXJ -GUY9sFgyvWkav+O74gzcv8y69uJzSOx0piOP+sfpZWVeGEjqO4JgdcS5NPMrT5Tb -aJ52CjiOdlHVTyR87i5JmOIvA2qA4dWQmSbX7AQ8r9ptYDe9xMn+qFegcbr4YxCz -K9mmbDZUhlLO7cz3QV6nvRxGFWbzffo8BXZnOUCAOyOHrbnPpLumnfZlL5BckdtY -pS7jAlUpKSMBTK4AHcmrouFsNKHqlUopYXeJFdg9g1F0DuCnVP9x7+XcUW8dAVut -Q7Jswy+++GAXs6mPVsYFLXUSYNyW+Bfl/jKwx0XTQx/6iyNpK0XtAzjBZFjXwmot -0mODkqnfE3BB4lXxZ5knomAQEGSScUhCUb9upbF4uJJF27xr/kIkwtWxMGpCXds0 -IxI+wNRCenhfFZEIQCzri0zn6WdN8b/gbv1BErNcccYwolPUv1oUgYbzowbQ5O2D -aLQPqO1VAZiZHLxb787bRywpCl33VZ1ptMHi2ogKjcsh4DQ9SsRj+rU/Tk5lyk7G -FHteyHcq12TGpz9/CQYMacl8yeRRHfNO3Rq0jFTYeD4+ZdVBPKeuTHyXGzy2T157 -pgqMFzwqxlNYPzpuz7xsZBExJzCtcomB8fMlsCJnxV/kuMTTsWsPrRc7hsqzBCq3 -plfYT8a7EBCVmJmDu+6mMVh+A9M2zZCqtV57AgMBAAGjIzAhMA4GA1UdDwEB/wQE -AwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQDRmkBYDk/F -lYTgMaL7yhRAowDR8mtOl06Oba/MCDDsmBvfOVIqY9Sa9sJtb78Uvecv9WAE4qpb -PNSaIvNmujmGQrBxtGwQdeHZvtXQ1lKAGBM+ukfz/NFU+6rwOdTuLgS5jTaiM4r1 -uMoIG6S5z/brWGHAw8Qv2Fq05dSLnevmPWK903V/RnwmCKT9as5Qpfkaie2PNory -euxVGeGolxzgbSps3ZJlDSSymQBl10iJYYdGIsgcw5FHcCdpS4AutdpQbIFuCGk2 -CHTcTTa4KMaVfRm/gKm1gh8UnuVDLBKQS8+1CHFYUnih8ozBNUyBo5r5L4BHJK/n -f0gnrYqaxtqPAyHkfo0PRc50HlAQRS/gW8ESv2PQmcSWlDggEzXt5MqFIYOfEXWE -gtC7Ct1P7gzIRxolYVsNSgBR62sJM1PUa39E5v0QJsmuM51txHuw/PGqkkBlEwx9 -4u3FFXD9Pslg/g1l50Ek5O3/TWMta4Q+NagDDaOdkb4LRQr522ySgGIinBw00Xr+ -Ics2L42rP1LQyaE7+BljDEwmGaT7mrl8QGZR9uv/9mbtk2+q7wAOQzcMSFFACfwx -KdKENmK0GpQZ6HaeDZO7wxGiAyFKhTNpd39XNOEhaKpWLSUxnZTLGlMIzvSyMGCj -PV3xm+Xg1Xvki7f/qC1djysMcaokoJzNdg== ------END CERTIFICATE----- -` - caPrivPem = `-----BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEA2Owc3IOljq3hkKO9q6jT1kFZp/+Y9dv/lTIbsMhV7gPrn2WS -Os2KQphcrB9DvGoZAxUh1aD8MUO7USIMhFodQEq7vfycDT16jrTnc1fSDDcfk3Ra -DvqZGcBkj0lc6w5LK3FNl2y6rA/26teGbyNaVXJfW01dKKy4E2or2+1+tUamyjiU -cvPzNWEoPPJT5HcadLTxZr/SKDvDXFyej4nKT9+j1pKmaqQrIrL4KXKq75LhU+kH -L4TG+kJ35isiv5OTpd2jG6ssz0i+ZEtX4hjIM6eCnZaiFT//33nSL3zl2LUjmyou -ks2FDuX9m90mg8UtcrpA/eVlwyg8nJ/d7/Yn3ZjuHVOgzE8YuQXauJ16HuLcFgEW -WQg1uwhOhrc5b0YJndZbJ2Re4qfaBoC5fODRXoUPvqG9k9kNp98xtclNCIyW8EpA -Su8QmK42ksOJox+OQamHzatrGppgIK77TY3ZFcBHETHClabgsfjv/1GNXXAexJI4 -Cjntnou+yoc+LUj87WJfD3ERGgm0nDfnE7uZ7kccO5Lj/oajeO+Q+QJaLZ4I2jz+ -a05k16naGGT29AnM+iwBqqoTODr4Z7905niZc6+fEOPml1V7wSuJs2eE4jOa3ixX -5tnruw74rN82Zfrkg6kWPOEfBBXzSotRiHv+BAV2tFbnC55ItnHn1ZE68V0CAwEA -AQKCAgEAssWsZ4PLXpIo8qYve5hQtSP4er7oVb8wnMnGDmSchOMQPbZc1D9uscGV -pnjBvzcFVAgHcWMSVJuIda4E+NK3hrPQlBvqk/LV3WRz1xhKUKzhRgm+6tdWc+We -OoRwonuOMchX9PKzyXgCu7pR3agaG499zOYuX4Yw0jdO3BqXsVf/v2rv1Oj9yEFB -AzGHOCN8VzCEPnTaAzR1pdnjB1K8vCUIhp8nrX2M2zT51lbdT0ISl6/VrzDTN46t -97AXHCHIrgrCENx6un4uAsQhMoHQBNoJiEyLWc371zYzpdVeK8HlDUyvQ2dDQGsF -Hn4c7r4C3aloRJbYzgSMJ1yNcOTCJpciQsq1VmCQFOHfbum2ejquXJ7BbeRGeHdM -145epckL+hbECTCpSs0Z5t90NdfoJspvr+3sOEt6h3DMUGjvobrf/s3KiRY5hHdc -x86Htx3QgWNCG6a+ga7h7s3t+4ZtoPPWn+vlAoxD/2eCzsDgE/XLDmC2T4yS8UOb -LIb4UN7wl2sNM8zhm4BfoiKfjGu4dPZIlsPP+ZKRby1O4ogHHoPREBTH1VSEplVM -fA/KSITV+rUfO3T/qXIFZ4/Wa5YZoULiMCOJOWNgXQzWvTf7Qr31LhhfXd+uIw30 -LDtjdkpT43zlKxRosQFLiV7q3fVbvKPVQfxzBz7M1Gl74IllpmECggEBAOnAimKl -w/9mcMkEd2L2ZzDI+57W8DU6grUUILZfjJG+uvOiMmIA5M1wzsVHil3ihZthrJ5A -UUAKG97JgwjpIAliAzgtPZY2AK/bJz7Hht1EwewrV+RyHM+dMv6em2OA+XUjFSPX -VsecFDaUQebkypw236KdA4jgRG6hr4xObdXgTN6RFCv1mI1EijZ/YbKgPgTJaPI4 -b2N5QokYFygUCwRxKIt7/Z4hQs9LbdW680NcXtPRPnS1SmwYJbi7wTX+o5f6nfNV -YvojborjXwNrZe0p+FfaEuD44wf6kNlRGfcKXoaAncXV/M5/oXf1dktKP630eq9g -0MAKFYJ6MAUheakCggEBAO2Rgfy/tEydBuP9BIfC84BXk8EwnRJ0ZfmXv77HFj3F -VT5QNU97I5gZJOFkL7OO8bL0/WljlqeBEht0DmHNmOt5Pyew4LRLpfeN6rClZgRN -V4wqKXjoZAIYa9khQcwwFNER1RdI+PkuusJtrvY6CbwwG9LbBq2NR4C1YSgaQnhV -NqdXK5dwrYEky6lI31sDD4BYeiJVKlkkNCQAVOC+04Mrsa9F0NG7TKXzji5hU8l5 -x8squjvJ6vmobhmsRTL1LMpafUrt5pHL9jcWIZYxJJo9mB0zxJKcsLI8IOg2QPoj -tQ395FZ2YtjNzZa1CYeUOUiaQu+uvztfE36AdW/vUpUCggEAMV7bW66LURw/4hUx -ahOFBAbPLmNTZMqw5LIVnq9br0TLk73ESnLJ4KJc6coMbXv0oDbnEJ2hC5eW/10s -cetbOuAasfjMMzfAuWPeTCI0V/O3ybv12mhHsYoQRTsWstOA3L7GLkXDLHHIyyZR -LQVRzeDBJ0Vmg7hqe7tmqom+JRg05CVcT1SWHfBGCPCqn+G8d6Jaqh5FWIs6BF60 -NWDWWt/TonJTxNxdkg7qaeQMkUOnO7HMMTZBO8d14Ci3zEG2J9llFwoH17E4Hdmc -Lcq3QnpE27lRl3a57Ot9QIkipMzp3hq4OBrURIEsh3uuuoQ6IvGqH/Sg4o6+sEpC -bjL90QKCAQBDc/0kdooK9sruEPkoUwIwfq1FPThb9RC/PYcD9CMshssdVkjMuHny -xbDjDj89DGk0FrudINm11b/+a4Vp36Z7tYFpE5+5kYEeOP1aCpxcvFkPQyljWxiK -P8TfccHs5/oBIr8OTXnjxpDgg6QZ5YC+HirIQ8gxntuef+GGMW6OHCPYf7ew2B1r -fbcV6csBXG0aVATZmrTbepwTXMS8y3Hi3JUm3vvbkQLCW9US9i+EFT/VP9yA/WPq -Xxhj0bYUMej1y5unmsTMwMy392Cx9GIgKTz3jatStYq2ELyHMmBgpaLSxjP/GL4Y -MNce42hBRqS9KI+43jUN9oDiejbeAWXBAoIBACZKnS6EppNDSdos0f32J5TxEUxv -lF9AuVXEAPDR/m3+PlSRzrlf7uowdHTfsemHMSduL8weLNhduprwz4TmW9Fo6fSF -UePLNbXcMX3omAk+AKKOiexLG0fCXGW2zr4nHZJzTbK2+La3yLeUcoPu1puNpLiq -LVj2bH3zKWVRA9/ovuN6V5w18ojjdqOw4bw5qXcdZhoWLxI8Q9Oqua24f/dnRpuI -I8mRtPQ3+vuOKbTT+/80eAUpSfEKwAg1Mjgury9q1/B4Ib6hAGzpJuXxG7xQjnsJ -EFcN1kvdg5WGK41+fYMdexPaLamjhDGN0e1vxJfAukWIAsBMwp8wfEWZvzA= ------END RSA PRIVATE KEY----- -` -) - -func TestNode_AdaptWithCA(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb"), "testNode") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "testNode", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - ca, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPriv, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().Times(1).Return(ca) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(caPriv) - dbCurrent.EXPECT().SetCertificate(ca).Times(1) - dbCurrent.EXPECT().SetCertificateKey(caPriv).Times(1) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, err := AdaptFunc(monitor, namespace, nameLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestNode_AdaptWithoutCA(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb"), "testNode") - - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "testNode", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{}, - } - - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - dbCurrent.EXPECT().GetCertificate().Times(1).Return(nil) - dbCurrent.EXPECT().GetCertificateKey().Times(1).Return(nil) - dbCurrent.EXPECT().SetCertificate(gomock.Any()).Times(1) - dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).Times(1) - k8sClient.EXPECT().ApplySecret(gomock.Any()).Times(1).Return(nil) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, err := AdaptFunc(monitor, namespace, nameLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestNode_AdaptAlreadyExisting(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "testNs" - clusterDns := "testDns" - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "cockroachdb"), "testNode") - nodeLabels := map[string]string{ - "app.kubernetes.io/component": "cockroachdb", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": "testNode", - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - dbCurrent := coremock.NewMockDatabaseCurrent(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - secretList := &corev1.SecretList{ - Items: []corev1.Secret{{ - ObjectMeta: metav1.ObjectMeta{}, - Data: map[string][]byte{ - caCertKey: []byte(caPem), - caPrivKeyKey: []byte(caPrivPem), - }, - Type: "Opaque", - }}, - } - - caCert, err := pem.DecodeCertificate([]byte(caPem)) - assert.NoError(t, err) - caPrivKey, err := pem.DecodeKey([]byte(caPrivPem)) - assert.NoError(t, err) - - dbCurrent.EXPECT().SetCertificate(caCert).Times(1) - dbCurrent.EXPECT().SetCertificateKey(caPrivKey).Times(1) - k8sClient.EXPECT().ListSecrets(namespace, nodeLabels).Times(1).Return(secretList, nil) - - queried := map[string]interface{}{} - current := &tree.Tree{ - Parsed: dbCurrent, - } - - core.SetQueriedForDatabase(queried, current) - - query, _, err := AdaptFunc(monitor, namespace, nameLabels, clusterDns, true) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) - -} diff --git a/operator/database/kinds/databases/managed/certificate/pem/pem.go b/operator/database/kinds/databases/managed/certificate/pem/pem.go deleted file mode 100644 index 489d52e0a7..0000000000 --- a/operator/database/kinds/databases/managed/certificate/pem/pem.go +++ /dev/null @@ -1,48 +0,0 @@ -package pem - -import ( - "bytes" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -func EncodeCertificate(data []byte) ([]byte, error) { - certPem := new(bytes.Buffer) - if err := pem.Encode(certPem, &pem.Block{ - Type: "CERTIFICATE", - Bytes: data, - }); err != nil { - return nil, err - } - return certPem.Bytes(), nil -} - -func EncodeKey(key *rsa.PrivateKey) ([]byte, error) { - keyPem := new(bytes.Buffer) - if err := pem.Encode(keyPem, &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(key), - }); err != nil { - return nil, err - } - return keyPem.Bytes(), nil -} - -func DecodeKey(data []byte) (*rsa.PrivateKey, error) { - block, _ := pem.Decode(data) - if block == nil || block.Type != "RSA PRIVATE KEY" { - return nil, errors.New("failed to decode PEM block containing public key") - } - - return x509.ParsePKCS1PrivateKey(block.Bytes) -} - -func DecodeCertificate(data []byte) ([]byte, error) { - block, _ := pem.Decode(data) - if block == nil || block.Type != "CERTIFICATE" { - return nil, errors.New("failed to decode PEM block containing public key") - } - return block.Bytes, nil -} diff --git a/operator/database/kinds/databases/managed/current.go b/operator/database/kinds/databases/managed/current.go deleted file mode 100644 index 9937248f11..0000000000 --- a/operator/database/kinds/databases/managed/current.go +++ /dev/null @@ -1,73 +0,0 @@ -package managed - -import ( - "crypto/rsa" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate" -) - -type Current struct { - Common *tree.Common `yaml:",inline"` - Current *CurrentDB -} - -type CurrentDB struct { - URL string - Port string - ReadyFunc operator.EnsureFunc - CA *certificate.Current - AddUserFunc func(user string) (operator.QueryFunc, error) - DeleteUserFunc func(user string) (operator.DestroyFunc, error) - ListUsersFunc func(k8sClient kubernetes.ClientInt) ([]string, error) - ListDatabasesFunc func(k8sClient kubernetes.ClientInt) ([]string, error) -} - -func (c *Current) GetURL() string { - return c.Current.URL -} - -func (c *Current) GetPort() string { - return c.Current.Port -} - -func (c *Current) GetReadyQuery() operator.EnsureFunc { - return c.Current.ReadyFunc -} - -func (c *Current) GetCA() *certificate.Current { - return c.Current.CA -} - -func (c *Current) GetCertificateKey() *rsa.PrivateKey { - return c.Current.CA.CertificateKey -} - -func (c *Current) SetCertificateKey(key *rsa.PrivateKey) { - c.Current.CA.CertificateKey = key -} - -func (c *Current) GetCertificate() []byte { - return c.Current.CA.Certificate -} - -func (c *Current) SetCertificate(cert []byte) { - c.Current.CA.Certificate = cert -} - -func (c *Current) GetListDatabasesFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) { - return c.Current.ListDatabasesFunc -} - -func (c *Current) GetListUsersFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) { - return c.Current.ListUsersFunc -} - -func (c *Current) GetAddUserFunc() func(user string) (operator.QueryFunc, error) { - return c.Current.AddUserFunc -} - -func (c *Current) GetDeleteUserFunc() func(user string) (operator.DestroyFunc, error) { - return c.Current.DeleteUserFunc -} diff --git a/operator/database/kinds/databases/managed/database/adapt.go b/operator/database/kinds/databases/managed/database/adapt.go deleted file mode 100644 index 92b83ab524..0000000000 --- a/operator/database/kinds/databases/managed/database/adapt.go +++ /dev/null @@ -1,50 +0,0 @@ -package database - -import ( - "fmt" - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - deployName string, - containerName string, - certsDir string, - userName string, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - cmdSql := fmt.Sprintf("cockroach sql --certs-dir=%s", certsDir) - - createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s ", userName) - - deleteSql := fmt.Sprintf("DROP DATABASE IF EXISTS %s", userName) - - ensureDatabase := func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ExecInPodOfDeployment(namespace, deployName, containerName, fmt.Sprintf("%s -e '%s;'", cmdSql, createSql)) - } - - destroyDatabase := func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ExecInPodOfDeployment(namespace, deployName, containerName, fmt.Sprintf("%s -e '%s;'", cmdSql, deleteSql)) - } - - queriers := []operator.QueryFunc{ - operator.EnsureFuncToQueryFunc(ensureDatabase), - } - - destroyers := []operator.DestroyFunc{ - destroyDatabase, - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - nil -} diff --git a/operator/database/kinds/databases/managed/desired.go b/operator/database/kinds/databases/managed/desired.go deleted file mode 100644 index 8ff892b449..0000000000 --- a/operator/database/kinds/databases/managed/desired.go +++ /dev/null @@ -1,44 +0,0 @@ -package managed - -import ( - "fmt" - - corev1 "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/caos/orbos/pkg/tree" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec Spec -} - -type Spec struct { - Verbose bool - Force bool `yaml:"force,omitempty"` - ReplicaCount int `yaml:"replicaCount,omitempty"` - StorageCapacity string `yaml:"storageCapacity,omitempty"` - StorageClass string `yaml:"storageClass,omitempty"` - NodeSelector map[string]string `yaml:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `yaml:"tolerations,omitempty"` - ClusterDns string `yaml:"clusterDNS,omitempty"` - Backups map[string]*tree.Tree `yaml:"backups,omitempty"` - Resources *k8s.Resources `yaml:"resources,omitempty"` - MaxSQLMemory string `yaml:"maxSqlMemory,omitempty"` - Cache string `yaml:"cache,omitempty"` -} - -func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{ - Common: desiredTree.Common, - Spec: Spec{}, - } - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed")) - } - - return desiredKind, nil -} diff --git a/operator/database/kinds/databases/managed/listbackups.go b/operator/database/kinds/databases/managed/listbackups.go deleted file mode 100644 index 851d8f9b61..0000000000 --- a/operator/database/kinds/databases/managed/listbackups.go +++ /dev/null @@ -1,39 +0,0 @@ -package managed - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator/database/kinds/backups" -) - -func BackupList() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) { - return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) { - desiredKind, err := parseDesiredV0(desired) - if err != nil { - return nil, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - monitor.Verbose() - } - - backuplists := make([]string, 0) - if desiredKind.Spec.Backups != nil { - for name, def := range desiredKind.Spec.Backups { - backuplist, err := backups.GetBackupList(monitor, k8sClient, name, def) - if err != nil { - return nil, err - } - for _, backup := range backuplist { - backuplists = append(backuplists, name+"."+backup) - } - } - } - return backuplists, nil - } -} diff --git a/operator/database/kinds/databases/managed/mock.go b/operator/database/kinds/databases/managed/mock.go deleted file mode 100644 index 46ebd7e08f..0000000000 --- a/operator/database/kinds/databases/managed/mock.go +++ /dev/null @@ -1,35 +0,0 @@ -package managed - -import ( - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - core "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "time" -) - -func SetClean( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - replicas int, -) { - k8sClient.EXPECT().ScaleStatefulset(namespace, gomock.Any(), 0).Return(nil) - k8sClient.EXPECT().ListPersistentVolumeClaims(namespace).Return(&core.PersistentVolumeClaimList{ - Items: []core.PersistentVolumeClaim{ - {ObjectMeta: metav1.ObjectMeta{ - Name: "datadir-cockroachdb-0", - }}, - }, - }, nil) - k8sClient.EXPECT().ScaleStatefulset(namespace, gomock.Any(), 1).Return(nil) - k8sClient.EXPECT().DeletePersistentVolumeClaim(namespace, gomock.Any(), gomock.Any()).Times(replicas).Return(nil) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, gomock.Any(), true, false, gomock.Any()) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, gomock.Any(), true, true, time.Second*1) - k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, gomock.Any(), true, true, gomock.Any()) - - /* - k8sClient.EXPECT().ApplyJob(gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().GetJob(namespace, clean.GetJobName(backupName)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, clean.GetJobName(backupName))) - k8sClient.EXPECT().WaitUntilJobCompleted(namespace, clean.GetJobName(backupName), gomock.Any()).Times(1).Return(nil) - k8sClient.EXPECT().DeleteJob(namespace, clean.GetJobName(backupName)).Times(1).Return(nil)*/ -} diff --git a/operator/database/kinds/databases/managed/rbac/adapt.go b/operator/database/kinds/databases/managed/rbac/adapt.go deleted file mode 100644 index fad86b1a82..0000000000 --- a/operator/database/kinds/databases/managed/rbac/adapt.go +++ /dev/null @@ -1,106 +0,0 @@ -package rbac - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/clusterrole" - "github.com/caos/orbos/pkg/kubernetes/resources/clusterrolebinding" - "github.com/caos/orbos/pkg/kubernetes/resources/role" - "github.com/caos/orbos/pkg/kubernetes/resources/rolebinding" - "github.com/caos/orbos/pkg/kubernetes/resources/serviceaccount" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - nameLabels *labels.Name, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - - internalMonitor := monitor.WithField("component", "rbac") - - serviceAccountLabels := nameLabels - roleLabels := nameLabels - clusterRoleLabels := nameLabels - - destroySA, err := serviceaccount.AdaptFuncToDestroy(namespace, serviceAccountLabels.Name()) - if err != nil { - return nil, nil, err - } - - destroyR, err := role.AdaptFuncToDestroy(roleLabels.Name(), namespace) - if err != nil { - return nil, nil, err - } - - destroyCR, err := clusterrole.AdaptFuncToDestroy(clusterRoleLabels.Name()) - if err != nil { - return nil, nil, err - } - - destroyRB, err := rolebinding.AdaptFuncToDestroy(namespace, roleLabels.Name()) - if err != nil { - return nil, nil, err - } - - destroyCRB, err := clusterrolebinding.AdaptFuncToDestroy(roleLabels.Name()) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyR), - operator.ResourceDestroyToZitadelDestroy(destroyCR), - operator.ResourceDestroyToZitadelDestroy(destroyRB), - operator.ResourceDestroyToZitadelDestroy(destroyCRB), - operator.ResourceDestroyToZitadelDestroy(destroySA), - } - - querySA, err := serviceaccount.AdaptFuncToEnsure(namespace, serviceAccountLabels) - if err != nil { - return nil, nil, err - } - - queryR, err := role.AdaptFuncToEnsure(namespace, roleLabels, []string{""}, []string{"secrets"}, []string{"create", "get"}) - if err != nil { - return nil, nil, err - } - - queryCR, err := clusterrole.AdaptFuncToEnsure(clusterRoleLabels, []string{"certificates.k8s.io"}, []string{"certificatesigningrequests"}, []string{"create", "get", "watch"}) - if err != nil { - return nil, nil, err - } - - subjects := []rolebinding.Subject{{Kind: "ServiceAccount", Name: serviceAccountLabels.Name(), Namespace: namespace}} - queryRB, err := rolebinding.AdaptFuncToEnsure(namespace, roleLabels, subjects, roleLabels.Name()) - if err != nil { - return nil, nil, err - } - - subjectsCRB := []clusterrolebinding.Subject{{Kind: "ServiceAccount", Name: serviceAccountLabels.Name(), Namespace: namespace}} - queryCRB, err := clusterrolebinding.AdaptFuncToEnsure(roleLabels, subjectsCRB, roleLabels.Name()) - if err != nil { - return nil, nil, err - } - - queriers := []operator.QueryFunc{ - //serviceaccount - operator.ResourceQueryToZitadelQuery(querySA), - //rbac - operator.ResourceQueryToZitadelQuery(queryR), - operator.ResourceQueryToZitadelQuery(queryCR), - operator.ResourceQueryToZitadelQuery(queryRB), - operator.ResourceQueryToZitadelQuery(queryCRB), - } - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil - -} diff --git a/operator/database/kinds/databases/managed/rbac/adapt_test.go b/operator/database/kinds/databases/managed/rbac/adapt_test.go deleted file mode 100644 index ad0a2f0e1c..0000000000 --- a/operator/database/kinds/databases/managed/rbac/adapt_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package rbac - -import ( - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" -) - -func TestRbac_Adapt1(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs" - name := "testName" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - } - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "testComponent"), name) - - queried := map[string]interface{}{} - - k8sClient.EXPECT().ApplyServiceAccount(&corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }}) - - k8sClient.EXPECT().ApplyRole(&rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{""}, - Resources: []string{"secrets"}, - Verbs: []string{"create", "get"}, - }, - }, - }) - k8sClient.EXPECT().ApplyClusterRole(&rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: k8sLabels, - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{"certificates.k8s.io"}, - Resources: []string{"certificatesigningrequests"}, - Verbs: []string{"create", "get", "watch"}, - }, - }, - }) - k8sClient.EXPECT().ApplyRoleBinding(&rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Subjects: []rbacv1.Subject{{ - Kind: "ServiceAccount", - Name: name, - Namespace: namespace, - }}, - RoleRef: rbacv1.RoleRef{ - Name: name, - Kind: "Role", - APIGroup: "rbac.authorization.k8s.io", - }, - }) - - k8sClient.EXPECT().ApplyClusterRoleBinding(&rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: k8sLabels, - }, - Subjects: []rbacv1.Subject{{ - Kind: "ServiceAccount", - Name: name, - Namespace: namespace, - }}, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Name: name, - Kind: "ClusterRole", - }, - }) - - query, _, err := AdaptFunc(monitor, namespace, nameLabels) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestRbac_Adapt2(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs2" - name := "testName2" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testVersion2", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - } - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "cockroachdb", "v0"), "testComponent2"), name) - - queried := map[string]interface{}{} - - k8sClient.EXPECT().ApplyServiceAccount(&corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }}) - - k8sClient.EXPECT().ApplyRole(&rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{""}, - Resources: []string{"secrets"}, - Verbs: []string{"create", "get"}, - }, - }, - }) - k8sClient.EXPECT().ApplyClusterRole(&rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: k8sLabels, - }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{"certificates.k8s.io"}, - Resources: []string{"certificatesigningrequests"}, - Verbs: []string{"create", "get", "watch"}, - }, - }, - }) - k8sClient.EXPECT().ApplyRoleBinding(&rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Subjects: []rbacv1.Subject{{ - Kind: "ServiceAccount", - Name: name, - Namespace: namespace, - }}, - RoleRef: rbacv1.RoleRef{ - Name: name, - Kind: "Role", - APIGroup: "rbac.authorization.k8s.io", - }, - }) - - k8sClient.EXPECT().ApplyClusterRoleBinding(&rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: k8sLabels, - }, - Subjects: []rbacv1.Subject{{ - Kind: "ServiceAccount", - Name: name, - Namespace: namespace, - }}, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Name: name, - Kind: "ClusterRole", - }, - }) - - query, _, err := AdaptFunc(monitor, namespace, nameLabels) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/services/adapt.go b/operator/database/kinds/databases/managed/services/adapt.go deleted file mode 100644 index ddda22d158..0000000000 --- a/operator/database/kinds/databases/managed/services/adapt.go +++ /dev/null @@ -1,79 +0,0 @@ -package services - -import ( - "github.com/caos/zitadel/operator" - "strconv" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/service" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - publicServiceNameLabels *labels.Name, - privateServiceNameLabels *labels.Name, - cockroachSelector *labels.Selector, - cockroachPort int32, - cockroachHTTPPort int32, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("type", "services") - - publicServiceSelectable := labels.AsSelectable(publicServiceNameLabels) - - destroySPD, err := service.AdaptFuncToDestroy("default", publicServiceSelectable.Name()) - if err != nil { - return nil, nil, err - } - destroySP, err := service.AdaptFuncToDestroy(namespace, publicServiceSelectable.Name()) - if err != nil { - return nil, nil, err - } - destroyS, err := service.AdaptFuncToDestroy(namespace, privateServiceNameLabels.Name()) - if err != nil { - return nil, nil, err - } - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroySPD), - operator.ResourceDestroyToZitadelDestroy(destroySP), - operator.ResourceDestroyToZitadelDestroy(destroyS), - } - - ports := []service.Port{ - {Port: 26257, TargetPort: strconv.Itoa(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: strconv.Itoa(int(cockroachHTTPPort)), Name: "http"}, - } - querySPD, err := service.AdaptFuncToEnsure("default", publicServiceSelectable, ports, "", cockroachSelector, false, "", "") - if err != nil { - return nil, nil, err - } - querySP, err := service.AdaptFuncToEnsure(namespace, publicServiceSelectable, ports, "", cockroachSelector, false, "", "") - if err != nil { - return nil, nil, err - } - queryS, err := service.AdaptFuncToEnsure(namespace, privateServiceNameLabels, ports, "", cockroachSelector, true, "None", "") - if err != nil { - return nil, nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(querySPD), - operator.ResourceQueryToZitadelQuery(querySP), - operator.ResourceQueryToZitadelQuery(queryS), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil - -} diff --git a/operator/database/kinds/databases/managed/services/adapt_test.go b/operator/database/kinds/databases/managed/services/adapt_test.go deleted file mode 100644 index 28b16596f2..0000000000 --- a/operator/database/kinds/databases/managed/services/adapt_test.go +++ /dev/null @@ -1,218 +0,0 @@ -package services - -import ( - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "testing" -) - -func TestService_Adapt1(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "testComponent") - - name := "testSvc" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - } - nameLabels := labels.MustForName(componentLabels, name) - publicName := "testPublic" - k8sPublicLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": publicName, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - "orbos.ch/selectable": "yes", - } - publicNameLabels := labels.MustForName(componentLabels, publicName) - - cdbName := "testCdbName" - k8sCdbLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": cdbName, - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - cdbNameLabels := labels.MustForName(componentLabels, cdbName) - - cockroachPort := int32(25267) - cockroachHttpPort := int32(8080) - queried := map[string]interface{}{} - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: publicName, - Namespace: namespace, - Labels: k8sPublicLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: false, - }, - }) - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: publicName, - Namespace: "default", - Labels: k8sPublicLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: false, - }, - }) - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: true, - ClusterIP: "None", - }, - }) - - query, _, err := AdaptFunc(monitor, namespace, publicNameLabels, nameLabels, labels.DeriveNameSelector(cdbNameLabels, false), cockroachPort, cockroachHttpPort) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestService_Adapt2(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs2" - componentLabels := labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "cockroachdb", "v0"), "testComponent2") - - name := "testSvc2" - k8sLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testVersion2", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - } - nameLabels := labels.MustForName(componentLabels, name) - publicName := "testPublic2" - k8sPublicLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": publicName, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testVersion2", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - "orbos.ch/selectable": "yes", - } - publicNameLabels := labels.MustForName(componentLabels, publicName) - - cdbName := "testCdbName2" - k8sCdbLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": cdbName, - "app.kubernetes.io/part-of": "testProd2", - "orbos.ch/selectable": "yes", - } - cdbNameLabels := labels.MustForName(componentLabels, cdbName) - cockroachPort := int32(23) - cockroachHttpPort := int32(24) - queried := map[string]interface{}{} - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: publicName, - Namespace: namespace, - Labels: k8sPublicLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: false, - }, - }) - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: publicName, - Namespace: "default", - Labels: k8sPublicLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: false, - }, - }) - - k8sClient.EXPECT().ApplyService(&corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sLabels, - }, - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Port: 26257, TargetPort: intstr.FromInt(int(cockroachPort)), Name: "grpc"}, - {Port: 8080, TargetPort: intstr.FromInt(int(cockroachHttpPort)), Name: "http"}, - }, - Selector: k8sCdbLabels, - PublishNotReadyAddresses: true, - ClusterIP: "None", - }, - }) - - query, _, err := AdaptFunc(monitor, namespace, publicNameLabels, nameLabels, labels.DeriveNameSelector(cdbNameLabels, false), cockroachPort, cockroachHttpPort) - assert.NoError(t, err) - - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/database/kinds/databases/managed/statefulset/adapt.go b/operator/database/kinds/databases/managed/statefulset/adapt.go deleted file mode 100644 index 759f008fa5..0000000000 --- a/operator/database/kinds/databases/managed/statefulset/adapt.go +++ /dev/null @@ -1,373 +0,0 @@ -package statefulset - -import ( - "errors" - "fmt" - "sort" - "strings" - "time" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/caos/orbos/pkg/kubernetes/resources" - "github.com/caos/orbos/pkg/kubernetes/resources/statefulset" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/helpers" -) - -const ( - certPath = "/cockroach/cockroach-certs" - clientCertPath = "/cockroach/cockroach-client-certs" - datadirPath = "/cockroach/cockroach-data" - datadirInternal = "datadir" - certsInternal = "certs" - clientCertsInternal = "client-certs" - defaultMode = int32(256) - nodeSecret = "cockroachdb.node" - rootSecret = "cockroachdb.client.root" - cleanTimeout = time.Minute * 5 -) - -type Affinity struct { - key string - value string -} - -type Affinitys []metav1.LabelSelectorRequirement - -func (a Affinitys) Len() int { return len(a) } -func (a Affinitys) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a Affinitys) Less(i, j int) bool { return a[i].Key < a[j].Key } - -func AdaptFunc( - monitor mntr.Monitor, - sfsSelectable *labels.Selectable, - podSelector *labels.Selector, - force bool, - namespace string, - image string, - serviceAccountName string, - replicaCount int, - storageCapacity resource.Quantity, - dbPort int32, - httpPort int32, - storageClass string, - nodeSelector map[string]string, - tolerations []corev1.Toleration, - resourcesSFS *k8s.Resources, - cache string, - maxSqlMemory string, -) ( - resources.QueryFunc, - resources.DestroyFunc, - operator.EnsureFunc, - operator.EnsureFunc, - func(k8sClient kubernetes.ClientInt) ([]string, error), - error, -) { - internalMonitor := monitor.WithField("component", "statefulset") - - name := sfsSelectable.Name() - k8sSelectable := labels.MustK8sMap(sfsSelectable) - statefulsetDef := &appsv1.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sSelectable, - }, - Spec: appsv1.StatefulSetSpec{ - ServiceName: name, - Replicas: helpers.PointerInt32(int32(replicaCount)), - Selector: &metav1.LabelSelector{ - MatchLabels: labels.MustK8sMap(podSelector), - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: k8sSelectable, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeSelector, - Tolerations: tolerations, - ServiceAccountName: serviceAccountName, - Affinity: getAffinity(k8sSelectable), - Containers: []corev1.Container{{ - Name: name, - Image: image, - ImagePullPolicy: "IfNotPresent", - Ports: []corev1.ContainerPort{ - {ContainerPort: dbPort, Name: "grpc"}, - {ContainerPort: httpPort, Name: "http"}, - }, - LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 30, - PeriodSeconds: 5, - }, - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health?ready=1", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 10, - PeriodSeconds: 5, - FailureThreshold: 2, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: datadirInternal, - MountPath: datadirPath, - }, { - Name: certsInternal, - MountPath: certPath, - }, { - Name: clientCertsInternal, - MountPath: clientCertPath, - }}, - Env: []corev1.EnvVar{{ - Name: "COCKROACH_CHANNEL", - Value: "kubernetes-multiregion", - }}, - Command: []string{ - "/bin/bash", - "-ecx", - getJoinExec( - namespace, - name, - int(dbPort), - replicaCount, - getCache(cache), - getMaxSqlMemory(maxSqlMemory), - ), - }, - Resources: getResources(resourcesSFS), - }}, - Volumes: []corev1.Volume{{ - Name: datadirInternal, - VolumeSource: corev1.VolumeSource{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: datadirInternal, - }, - }, - }, { - Name: certsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: nodeSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: clientCertsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }}, - }, - }, - PodManagementPolicy: appsv1.ParallelPodManagement, - UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ - Type: "RollingUpdate", - }, - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{{ - ObjectMeta: metav1.ObjectMeta{ - Name: datadirInternal, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.PersistentVolumeAccessMode("ReadWriteOnce"), - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "storage": storageCapacity, - }, - }, - StorageClassName: &storageClass, - }, - }}, - }, - } - - query, err := statefulset.AdaptFuncToEnsure(statefulsetDef, force) - if err != nil { - return nil, nil, nil, nil, nil, err - } - destroy, err := statefulset.AdaptFuncToDestroy(namespace, name) - if err != nil { - return nil, nil, nil, nil, nil, err - } - - wrapedQuery, wrapedDestroy, err := resources.WrapFuncs(internalMonitor, query, destroy) - checkDBRunning := func(k8sClient kubernetes.ClientInt) error { - internalMonitor.Info("waiting for statefulset to be running") - if err := k8sClient.WaitUntilStatefulsetIsReady(namespace, name, true, false, 60*time.Second); err != nil { - return fmt.Errorf("error while waiting for statefulset to be running: %w", err) - } - internalMonitor.Info("statefulset is running") - return nil - } - - checkDBNotReady := func(k8sClient kubernetes.ClientInt) error { - internalMonitor.Info("checking for statefulset to not be ready") - if err := k8sClient.WaitUntilStatefulsetIsReady(namespace, name, true, true, 1*time.Second); err != nil { - internalMonitor.Info("statefulset is not ready") - return nil - } - return errors.New("statefulset is ready") - } - - ensureInit := func(k8sClient kubernetes.ClientInt) error { - if err := checkDBRunning(k8sClient); err != nil { - return err - } - - if err := checkDBNotReady(k8sClient); err != nil { - return nil - } - - command := "/cockroach/cockroach init --certs-dir=" + clientCertPath + " --host=" + name + "-0." + name - - if err := k8sClient.ExecInPod(namespace, name+"-0", name, command); err != nil { - return err - } - return nil - } - - checkDBReady := func(k8sClient kubernetes.ClientInt) error { - internalMonitor.Info("waiting for statefulset to be ready") - if err := k8sClient.WaitUntilStatefulsetIsReady(namespace, name, true, true, 60*time.Second); err != nil { - return fmt.Errorf("error while waiting for statefulset to be ready: %w", err) - } - internalMonitor.Info("statefulset is ready") - return nil - } - - getAllDBs := func(k8sClient kubernetes.ClientInt) ([]string, error) { - if err := checkDBRunning(k8sClient); err != nil { - return nil, err - } - - if err := checkDBReady(k8sClient); err != nil { - return nil, err - } - - command := "/cockroach/cockroach sql --certs-dir=" + clientCertPath + " --host=" + name + "-0." + name + " -e 'SHOW DATABASES;'" - - databasesStr, err := k8sClient.ExecInPodWithOutput(namespace, name+"-0", name, command) - if err != nil { - return nil, err - } - databases := strings.Split(databasesStr, "\n") - dbAndOwners := databases[1 : len(databases)-1] - dbs := []string{} - for _, dbAndOwner := range dbAndOwners { - parts := strings.Split(dbAndOwner, "\t") - if parts[1] != "node" { - dbs = append(dbs, parts[0]) - } - } - return dbs, nil - } - - return wrapedQuery, wrapedDestroy, ensureInit, checkDBReady, getAllDBs, err -} - -func getJoinExec( - namespace string, - name string, - dbPort int, - replicaCount int, - cache string, - maxSqlMemory string, -) string { - joinList := make([]string, 0) - for i := 0; i < replicaCount; i++ { - joinList = append(joinList, fmt.Sprintf("%s-%d.%s.%s:%d", name, i, name, namespace, dbPort)) - } - joinListStr := strings.Join(joinList, ",") - locality := "zone=" + namespace - - return "exec /cockroach/cockroach start --logtostderr --certs-dir " + certPath + " --advertise-host $(hostname -f) --http-addr 0.0.0.0 --join " + joinListStr + " --locality " + locality + " --cache " + cache + " --max-sql-memory " + maxSqlMemory -} - -func getCache(cache string) string { - if cache != "" { - return cache - } - return "10%" -} - -func getMaxSqlMemory(maxSqlMemory string) string { - if maxSqlMemory != "" { - return maxSqlMemory - } - return "10%" -} - -func getResources(resourcesSFS *k8s.Resources) corev1.ResourceRequirements { - internalResources := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("1"), - "memory": resource.MustParse("6Gi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("4"), - "memory": resource.MustParse("8Gi"), - }, - } - - if resourcesSFS != nil { - internalResources = corev1.ResourceRequirements{} - if resourcesSFS.Requests != nil { - internalResources.Requests = resourcesSFS.Requests - } - if resourcesSFS.Limits != nil { - internalResources.Limits = resourcesSFS.Limits - } - } - - return internalResources -} - -func getAffinity(labels map[string]string) *corev1.Affinity { - affinity := Affinitys{} - for k, v := range labels { - affinity = append(affinity, metav1.LabelSelectorRequirement{ - Key: k, - Operator: metav1.LabelSelectorOpIn, - Values: []string{ - v, - }}) - } - sort.Sort(affinity) - - return &corev1.Affinity{ - PodAntiAffinity: &corev1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{{ - LabelSelector: &metav1.LabelSelector{ - MatchExpressions: affinity, - }, - TopologyKey: "kubernetes.io/hostname", - }}, - }, - } -} diff --git a/operator/database/kinds/databases/managed/statefulset/adapt_test.go b/operator/database/kinds/databases/managed/statefulset/adapt_test.go deleted file mode 100644 index e9f145efcc..0000000000 --- a/operator/database/kinds/databases/managed/statefulset/adapt_test.go +++ /dev/null @@ -1,525 +0,0 @@ -package statefulset - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes/k8s" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/helpers" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func TestStatefulset_JoinExec0(t *testing.T) { - namespace := "testNs" - name := "test" - dbPort := 26257 - replicaCount := 0 - cache := "" - maxSqlMemory := "" - - equals := "exec /cockroach/cockroach start --logtostderr --certs-dir /cockroach/cockroach-certs --advertise-host $(hostname -f) --http-addr 0.0.0.0 --join --locality zone=testNs --cache --max-sql-memory " - assert.Equal(t, equals, getJoinExec(namespace, name, dbPort, replicaCount, cache, maxSqlMemory)) -} - -func TestStatefulset_JoinExec1(t *testing.T) { - namespace := "testNs2" - name := "test2" - dbPort := 26257 - replicaCount := 1 - cache := "15%" - maxSqlMemory := "15%" - - equals := "exec /cockroach/cockroach start --logtostderr --certs-dir /cockroach/cockroach-certs --advertise-host $(hostname -f) --http-addr 0.0.0.0 --join test2-0.test2.testNs2:26257 --locality zone=testNs2 --cache 15% --max-sql-memory 15%" - assert.Equal(t, equals, getJoinExec(namespace, name, dbPort, replicaCount, cache, maxSqlMemory)) -} - -func TestStatefulset_JoinExec2(t *testing.T) { - namespace := "testNs" - name := "test" - dbPort := 23 - replicaCount := 2 - cache := "20%" - maxSqlMemory := "20%" - - equals := "exec /cockroach/cockroach start --logtostderr --certs-dir /cockroach/cockroach-certs --advertise-host $(hostname -f) --http-addr 0.0.0.0 --join test-0.test.testNs:23,test-1.test.testNs:23 --locality zone=testNs --cache 20% --max-sql-memory 20%" - assert.Equal(t, equals, getJoinExec(namespace, name, dbPort, replicaCount, cache, maxSqlMemory)) -} - -func TestStatefulset_Resources0(t *testing.T) { - equals := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("1"), - "memory": resource.MustParse("6Gi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("4"), - "memory": resource.MustParse("8Gi"), - }, - } - - assert.Equal(t, equals, getResources(nil)) -} - -func TestStatefulset_Resources1(t *testing.T) { - res := &k8s.Resources{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("600Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("126Mi"), - }, - } - - equals := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("200m"), - "memory": resource.MustParse("600Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("126Mi"), - }, - } - - assert.Equal(t, equals, getResources(res)) -} - -func TestStatefulset_Resources2(t *testing.T) { - res := &k8s.Resources{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("300m"), - "memory": resource.MustParse("670Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("600m"), - "memory": resource.MustParse("256Mi"), - }, - } - - equals := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "cpu": resource.MustParse("300m"), - "memory": resource.MustParse("670Mi"), - }, - Limits: corev1.ResourceList{ - "cpu": resource.MustParse("600m"), - "memory": resource.MustParse("256Mi"), - }, - } - - assert.Equal(t, equals, getResources(res)) -} - -func TestStatefulset_Adapt1(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs" - name := "test" - image := "cockroach" - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd", "testOp", "testVersion"), "cockroachdb", "v0"), "testComponent"), name) - k8sSelectableLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd", - "app.kubernetes.io/version": "testVersion", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - "orbos.ch/selectable": "yes", - } - k8sSelectorLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent", - "app.kubernetes.io/managed-by": "testOp", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd", - "orbos.ch/selectable": "yes", - } - selector := labels.DeriveNameSelector(nameLabels, false) - selectable := labels.AsSelectable(nameLabels) - - serviceAccountName := "testSA" - replicaCount := 1 - storageCapacity := "20Gi" - dbPort := int32(26257) - httpPort := int32(8080) - storageClass := "testSC" - nodeSelector := map[string]string{} - tolerations := []corev1.Toleration{} - resourcesSFS := &k8s.Resources{} - cache := "" - maxSqlMemory := "" - - quantity, err := resource.ParseQuantity(storageCapacity) - assert.NoError(t, err) - - sfs := &appsv1.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sSelectableLabels, - }, - Spec: appsv1.StatefulSetSpec{ - ServiceName: name, - Replicas: helpers.PointerInt32(int32(replicaCount)), - Selector: &metav1.LabelSelector{ - MatchLabels: k8sSelectorLabels, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: k8sSelectableLabels, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeSelector, - Tolerations: tolerations, - ServiceAccountName: serviceAccountName, - Affinity: getAffinity(k8sSelectableLabels), - Containers: []corev1.Container{{ - Name: name, - Image: image, - ImagePullPolicy: "IfNotPresent", - Ports: []corev1.ContainerPort{ - {ContainerPort: dbPort, Name: "grpc"}, - {ContainerPort: httpPort, Name: "http"}, - }, - LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 30, - PeriodSeconds: 5, - }, - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health?ready=1", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 10, - PeriodSeconds: 5, - FailureThreshold: 2, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: datadirInternal, - MountPath: datadirPath, - }, { - Name: certsInternal, - MountPath: certPath, - }, { - Name: clientCertsInternal, - MountPath: clientCertPath, - }}, - Env: []corev1.EnvVar{{ - Name: "COCKROACH_CHANNEL", - Value: "kubernetes-multiregion", - }}, - Command: []string{ - "/bin/bash", - "-ecx", - getJoinExec( - namespace, - name, - int(dbPort), - replicaCount, - getCache(cache), - getMaxSqlMemory(maxSqlMemory), - ), - }, - Resources: getResources(resourcesSFS), - }}, - Volumes: []corev1.Volume{{ - Name: datadirInternal, - VolumeSource: corev1.VolumeSource{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: datadirInternal, - }, - }, - }, { - Name: certsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: nodeSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: clientCertsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }}, - }, - }, - PodManagementPolicy: appsv1.PodManagementPolicyType("Parallel"), - UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ - Type: "RollingUpdate", - }, - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{{ - ObjectMeta: metav1.ObjectMeta{ - Name: datadirInternal, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.PersistentVolumeAccessMode("ReadWriteOnce"), - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "storage": quantity, - }, - }, - StorageClassName: &storageClass, - }, - }}, - }, - } - - k8sClient.EXPECT().ApplyStatefulSet(sfs, false) - - query, _, _, _, _, err := AdaptFunc( - monitor, - selectable, - selector, - false, - namespace, - image, - serviceAccountName, - replicaCount, - resource.MustParse(storageCapacity), - dbPort, - httpPort, - storageClass, - nodeSelector, - tolerations, - resourcesSFS, - cache, - maxSqlMemory, - ) - assert.NoError(t, err) - - ensure, err := query(k8sClient) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) -} - -func TestStatefulset_Adapt2(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - monitor := mntr.Monitor{} - namespace := "testNs2" - name := "test2" - image := "cockroach2" - - nameLabels := labels.MustForName(labels.MustForComponent(labels.MustForAPI(labels.MustForOperator("testProd2", "testOp2", "testVersion2"), "cockroachdb", "v0"), "testComponent2"), name) - k8sSelectableLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd2", - "app.kubernetes.io/version": "testVersion2", - "caos.ch/apiversion": "v0", - "caos.ch/kind": "cockroachdb", - "orbos.ch/selectable": "yes", - } - k8sSelectorLabels := map[string]string{ - "app.kubernetes.io/component": "testComponent2", - "app.kubernetes.io/managed-by": "testOp2", - "app.kubernetes.io/name": name, - "app.kubernetes.io/part-of": "testProd2", - "orbos.ch/selectable": "yes", - } - selector := labels.DeriveNameSelector(nameLabels, false) - selectable := labels.AsSelectable(nameLabels) - - serviceAccountName := "testSA2" - replicaCount := 2 - storageCapacity := "40Gi" - dbPort := int32(23) - httpPort := int32(24) - storageClass := "testSC2" - nodeSelector := map[string]string{} - tolerations := []corev1.Toleration{} - resourcesSFS := &k8s.Resources{} - cache := "20%" - maxSqlMemory := "20%" - - quantity, err := resource.ParseQuantity(storageCapacity) - assert.NoError(t, err) - - sfs := &appsv1.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - Labels: k8sSelectableLabels, - }, - Spec: appsv1.StatefulSetSpec{ - ServiceName: name, - Replicas: helpers.PointerInt32(int32(replicaCount)), - Selector: &metav1.LabelSelector{ - MatchLabels: k8sSelectorLabels, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: k8sSelectableLabels, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeSelector, - Tolerations: tolerations, - ServiceAccountName: serviceAccountName, - Affinity: getAffinity(k8sSelectableLabels), - Containers: []corev1.Container{{ - Name: name, - Image: image, - ImagePullPolicy: "IfNotPresent", - Ports: []corev1.ContainerPort{ - {ContainerPort: dbPort, Name: "grpc"}, - {ContainerPort: httpPort, Name: "http"}, - }, - LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 30, - PeriodSeconds: 5, - }, - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/health?ready=1", - Port: intstr.Parse("http"), - Scheme: "HTTPS", - }, - }, - InitialDelaySeconds: 10, - PeriodSeconds: 5, - FailureThreshold: 2, - }, - VolumeMounts: []corev1.VolumeMount{{ - Name: datadirInternal, - MountPath: datadirPath, - }, { - Name: certsInternal, - MountPath: certPath, - }, { - Name: clientCertsInternal, - MountPath: clientCertPath, - }}, - Env: []corev1.EnvVar{{ - Name: "COCKROACH_CHANNEL", - Value: "kubernetes-multiregion", - }}, - Command: []string{ - "/bin/bash", - "-ecx", - getJoinExec( - namespace, - name, - int(dbPort), - replicaCount, - getCache(cache), - getMaxSqlMemory(maxSqlMemory), - ), - }, - Resources: getResources(resourcesSFS), - }}, - Volumes: []corev1.Volume{{ - Name: datadirInternal, - VolumeSource: corev1.VolumeSource{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: datadirInternal, - }, - }, - }, { - Name: certsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: nodeSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }, { - Name: clientCertsInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: rootSecret, - DefaultMode: helpers.PointerInt32(defaultMode), - }, - }, - }}, - }, - }, - PodManagementPolicy: appsv1.PodManagementPolicyType("Parallel"), - UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ - Type: "RollingUpdate", - }, - VolumeClaimTemplates: []corev1.PersistentVolumeClaim{{ - ObjectMeta: metav1.ObjectMeta{ - Name: datadirInternal, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{ - corev1.PersistentVolumeAccessMode("ReadWriteOnce"), - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - "storage": quantity, - }, - }, - StorageClassName: &storageClass, - }, - }}, - }, - } - - k8sClient.EXPECT().ApplyStatefulSet(sfs, false) - - query, _, _, _, _, err := AdaptFunc( - monitor, - selectable, - selector, - false, - namespace, - image, - serviceAccountName, - replicaCount, - resource.MustParse(storageCapacity), - dbPort, - httpPort, - storageClass, - nodeSelector, - tolerations, - resourcesSFS, - cache, - maxSqlMemory, - ) - assert.NoError(t, err) - - ensure, err := query(k8sClient) - assert.NoError(t, err) - assert.NotNil(t, ensure) - - assert.NoError(t, ensure(k8sClient)) - -} diff --git a/operator/database/kinds/databases/managed/statefulset/clean.go b/operator/database/kinds/databases/managed/statefulset/clean.go deleted file mode 100644 index 3ce9e5a143..0000000000 --- a/operator/database/kinds/databases/managed/statefulset/clean.go +++ /dev/null @@ -1,60 +0,0 @@ -package statefulset - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources" - "github.com/caos/orbos/pkg/labels" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "strings" - "time" -) - -func CleanPVCs( - monitor mntr.Monitor, - namespace string, - sfsSelectable *labels.Selectable, - replicaCount int, -) resources.QueryFunc { - name := sfsSelectable.Name() - return func(k8sClient kubernetes.ClientInt) (resources.EnsureFunc, error) { - pvcs, err := k8sClient.ListPersistentVolumeClaims(namespace) - if err != nil { - return nil, err - } - internalPvcs := []string{} - for _, pvc := range pvcs.Items { - if strings.HasPrefix(pvc.Name, datadirInternal+"-"+name) { - internalPvcs = append(internalPvcs, pvc.Name) - } - } - return func(k8sClient kubernetes.ClientInt) error { - noSFS := false - monitor.Info("Scale down statefulset") - if err := k8sClient.ScaleStatefulset(namespace, name, 0); err != nil { - if macherrs.IsNotFound(err) { - noSFS = true - } else { - return err - } - } - time.Sleep(2 * time.Second) - - monitor.Info("Delete persistent volume claims") - for _, pvcName := range internalPvcs { - if err := k8sClient.DeletePersistentVolumeClaim(namespace, pvcName, cleanTimeout); err != nil { - return err - } - } - time.Sleep(2 * time.Second) - - if !noSFS { - monitor.Info("Scale up statefulset") - if err := k8sClient.ScaleStatefulset(namespace, name, replicaCount); err != nil { - return err - } - } - return nil - }, nil - } -} diff --git a/operator/database/kinds/databases/managed/user/adapt.go b/operator/database/kinds/databases/managed/user/adapt.go deleted file mode 100644 index d52ad909e9..0000000000 --- a/operator/database/kinds/databases/managed/user/adapt.go +++ /dev/null @@ -1,72 +0,0 @@ -package user - -import ( - "fmt" - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate" -) - -func AdaptFunc( - monitor mntr.Monitor, - namespace string, - deployName string, - containerName string, - certsDir string, - userName string, - password string, - componentLabels *labels.Component, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - cmdSql := fmt.Sprintf("cockroach sql --certs-dir=%s", certsDir) - - createSql := fmt.Sprintf("CREATE USER IF NOT EXISTS %s ", userName) - if password != "" { - createSql = fmt.Sprintf("%s WITH PASSWORD %s", createSql, password) - } - - deleteSql := fmt.Sprintf("DROP USER IF EXISTS %s", userName) - - _, _, addUserFunc, deleteUserFunc, _, err := certificate.AdaptFunc(monitor, namespace, componentLabels, "", false) - if err != nil { - return nil, nil, err - } - - addUser, err := addUserFunc(userName) - if err != nil { - return nil, nil, err - } - ensureUser := func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ExecInPodOfDeployment(namespace, deployName, containerName, fmt.Sprintf("%s -e '%s;'", cmdSql, createSql)) - } - - deleteUser, err := deleteUserFunc(userName) - if err != nil { - return nil, nil, err - } - destoryUser := func(k8sClient kubernetes.ClientInt) error { - return k8sClient.ExecInPodOfDeployment(namespace, deployName, containerName, fmt.Sprintf("%s -e '%s;'", cmdSql, deleteSql)) - } - - queriers := []operator.QueryFunc{ - addUser, - operator.EnsureFuncToQueryFunc(ensureUser), - } - - destroyers := []operator.DestroyFunc{ - destoryUser, - deleteUser, - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(monitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - nil -} diff --git a/operator/database/kinds/databases/provided/adapt.go b/operator/database/kinds/databases/provided/adapt.go deleted file mode 100644 index f7fa60467c..0000000000 --- a/operator/database/kinds/databases/provided/adapt.go +++ /dev/null @@ -1,55 +0,0 @@ -package provided - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator" -) - -func Adapter() operator.AdaptFunc { - return func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, - ) ( - operator.QueryFunc, - operator.DestroyFunc, - operator.ConfigureFunc, - map[string]*secret.Secret, - map[string]*secret.Existing, - bool, - error, - ) { - desiredKind, err := parseDesiredV0(desired) - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - currentDB := &Current{ - Common: tree.NewCommon("databases.caos.ch/ProvidedDatabase", "v0", false), - } - current.Parsed = currentDB - - return func(k8sClient kubernetes.ClientInt, _ map[string]interface{}) (operator.EnsureFunc, error) { - currentDB.Current.URL = desiredKind.Spec.URL - currentDB.Current.Port = desiredKind.Spec.Port - - return func(k8sClient kubernetes.ClientInt) error { - return nil - }, nil - }, func(k8sClient kubernetes.ClientInt) error { - return nil - }, - func(kubernetes.ClientInt, map[string]interface{}, bool) error { return nil }, - make(map[string]*secret.Secret), - make(map[string]*secret.Existing), - false, - nil - } -} diff --git a/operator/database/kinds/databases/provided/current.go b/operator/database/kinds/databases/provided/current.go deleted file mode 100644 index c3d3cd2bc6..0000000000 --- a/operator/database/kinds/databases/provided/current.go +++ /dev/null @@ -1,21 +0,0 @@ -package provided - -import ( - "github.com/caos/orbos/pkg/tree" -) - -type Current struct { - Common *tree.Common `yaml:",inline"` - Current struct { - URL string - Port string - } -} - -func (c *Current) GetURL() string { - return c.Current.URL -} - -func (c *Current) GetPort() string { - return c.Current.Port -} diff --git a/operator/database/kinds/databases/provided/desired.go b/operator/database/kinds/databases/provided/desired.go deleted file mode 100644 index 158070b7d1..0000000000 --- a/operator/database/kinds/databases/provided/desired.go +++ /dev/null @@ -1,34 +0,0 @@ -package provided - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/tree" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec Spec -} - -type Spec struct { - Verbose bool - Namespace string - URL string - Port string - Users []string -} - -func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{ - Common: desiredTree.Common, - Spec: Spec{}, - } - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err)) - } - - return desiredKind, nil -} diff --git a/operator/database/kinds/orb/adapt.go b/operator/database/kinds/orb/adapt.go deleted file mode 100644 index 9637509438..0000000000 --- a/operator/database/kinds/orb/adapt.go +++ /dev/null @@ -1,152 +0,0 @@ -package orb - -import ( - "fmt" - "github.com/caos/zitadel/operator/database/kinds/databases/managed" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/namespace" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/orbos/pkg/treelabels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" - "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" - "github.com/caos/zitadel/operator/database/kinds/databases" -) - -const ( - NamespaceStr = "caos-zitadel" -) - -func OperatorSelector() *labels.Selector { - return labels.OpenOperatorSelector("ZITADEL", "database.caos.ch") -} - -func AdaptFunc( - timestamp string, - binaryVersion *string, - gitops bool, - features ...string, -) operator.AdaptFunc { - - return func( - monitor mntr.Monitor, - orbDesiredTree *tree.Tree, - currentTree *tree.Tree, - ) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - configureFunc operator.ConfigureFunc, - secrets map[string]*secret.Secret, - existing map[string]*secret.Existing, - migrate bool, - err error, - ) { - defer func() { - if err != nil { - err = fmt.Errorf("building %s failed: %w", orbDesiredTree.Common.Kind, err) - } - }() - - orbMonitor := monitor.WithField("kind", "orb") - - desiredKind, err := ParseDesiredV0(orbDesiredTree) - if err != nil { - return nil, nil, nil, nil, nil, migrate, fmt.Errorf("parsing desired state failed: %w", err) - } - orbDesiredTree.Parsed = desiredKind - currentTree = &tree.Tree{} - - if desiredKind.Spec.Verbose && !orbMonitor.IsVerbose() { - orbMonitor = orbMonitor.Verbose() - } - - queryNS, err := namespace.AdaptFuncToEnsure(NamespaceStr) - if err != nil { - return nil, nil, nil, nil, nil, migrate, err - } - /*destroyNS, err := namespace.AdaptFuncToDestroy(NamespaceStr) - if err != nil { - return nil, nil, nil, err - }*/ - - databaseCurrent := &tree.Tree{} - - operatorLabels := mustDatabaseOperator(binaryVersion) - version := "" - if binaryVersion != nil { - version = *binaryVersion - } - - queryDB, destroyDB, configureDB, secrets, existing, migrate, err := databases.Adapt( - orbMonitor, - desiredKind.Database, - databaseCurrent, - NamespaceStr, - treelabels.MustForAPI(desiredKind.Database, operatorLabels), - timestamp, - desiredKind.Spec.NodeSelector, - desiredKind.Spec.Tolerations, - version, - features, - desiredKind.Spec.CustomImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, migrate, err - } - - rec, _ := Reconcile(monitor, desiredKind.Spec, gitops) - - destroyers := make([]operator.DestroyFunc, 0) - queriers := make([]operator.QueryFunc, 0) - dbOrBackup := false - for _, feature := range features { - switch feature { - case "database", backup.Instant, backup.Normal, restore.Instant, managed.Clean: - if !dbOrBackup { - dbOrBackup = true - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryNS), - queryDB, - ) - destroyers = append(destroyers, - destroyDB, - ) - } - case "operator": - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryNS), - operator.EnsureFuncToQueryFunc(rec), - ) - } - } - - currentTree.Parsed = &DesiredV0{ - Common: tree.NewCommon("databases.caos.ch/Orb", "v0", false), - Database: databaseCurrent, - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - if queried == nil { - queried = map[string]interface{}{} - } - monitor.WithField("queriers", len(queriers)).Info("Querying") - return operator.QueriersToEnsureFunc(monitor, true, queriers, k8sClient, queried) - }, - func(k8sClient kubernetes.ClientInt) error { - monitor.WithField("destroyers", len(queriers)).Info("Destroy") - return operator.DestroyersToDestroyFunc(monitor, destroyers)(k8sClient) - }, - func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, gitops bool) error { - return configureDB(k8sClient, queried, gitops) - }, - secrets, - existing, - migrate, - nil - } -} diff --git a/operator/database/kinds/orb/backups.go b/operator/database/kinds/orb/backups.go deleted file mode 100644 index 7974ca6ac2..0000000000 --- a/operator/database/kinds/orb/backups.go +++ /dev/null @@ -1,27 +0,0 @@ -package orb - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator/database/kinds/databases" -) - -func BackupListFunc() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) { - return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) { - desiredKind, err := ParseDesiredV0(desiredTree) - if err != nil { - return nil, fmt.Errorf("parsing desired state failed: %w", err) - } - desiredTree.Parsed = desiredKind - - if desiredKind.Spec.Verbose && !monitor.IsVerbose() { - monitor = monitor.Verbose() - } - - return databases.GetBackupList(monitor, k8sClient, desiredKind.Database) - } -} diff --git a/operator/database/kinds/orb/desired.go b/operator/database/kinds/orb/desired.go deleted file mode 100644 index 52a4ba3236..0000000000 --- a/operator/database/kinds/orb/desired.go +++ /dev/null @@ -1,38 +0,0 @@ -package orb - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/tree" - corev1 "k8s.io/api/core/v1" -) - -type DesiredV0 struct { - Common *tree.Common `json:",inline" yaml:",inline"` - Spec *Spec `json:"spec" yaml:"spec"` - Database *tree.Tree -} - -// +kubebuilder:object:generate=true -type Spec struct { - Verbose bool `json:"verbose" json:"verbose"` - NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"` - Version string `json:"version,omitempty" yaml:"version,omitempty"` - SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"` - //Use this registry to pull container images from - //@default: - CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` -} - -func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{Common: desiredTree.Common} - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err)) - } - desiredKind.Common.OverwriteVersion("v0") - - return desiredKind, nil -} diff --git a/operator/database/kinds/orb/labels.go b/operator/database/kinds/orb/labels.go deleted file mode 100644 index 5e5146746f..0000000000 --- a/operator/database/kinds/orb/labels.go +++ /dev/null @@ -1,13 +0,0 @@ -package orb - -import "github.com/caos/orbos/pkg/labels" - -func mustDatabaseOperator(binaryVersion *string) *labels.Operator { - - version := "unknown" - if binaryVersion != nil { - version = *binaryVersion - } - - return labels.MustForOperator("ZITADEL", "database.caos.ch", version) -} diff --git a/operator/database/kinds/orb/reconcile.go b/operator/database/kinds/orb/reconcile.go deleted file mode 100644 index 89c93df157..0000000000 --- a/operator/database/kinds/orb/reconcile.go +++ /dev/null @@ -1,50 +0,0 @@ -package orb - -import ( - "errors" - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/orbos/pkg/treelabels" - - "github.com/caos/zitadel/operator" - zitadelKubernetes "github.com/caos/zitadel/pkg/kubernetes" -) - -func Reconcile( - monitor mntr.Monitor, - spec *Spec, - gitops bool, -) ( - operator.EnsureFunc, - operator.DestroyFunc, -) { - return func(k8sClient kubernetes.ClientInt) (err error) { - recMonitor := monitor.WithField("version", spec.Version) - - if spec.Version == "" { - return errors.New("no version provided for self-reconciling") - } - - if spec.SelfReconciling { - desiredTree := &tree.Tree{ - Common: tree.NewCommon("databases.caos.ch/Orb", "v0", false), - } - - if err := zitadelKubernetes.EnsureDatabaseArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { - return fmt.Errorf("failed to deploy database-operator into k8s-cluster: %w", err) - } - recMonitor.Info("Applied database-operator") - } - return nil - }, func(k8sClient kubernetes.ClientInt) error { - if err := zitadelKubernetes.DestroyDatabaseOperator(monitor, labels.MustForAPI(labels.NoopOperator("database-operator"), "database", "v0"), k8sClient, gitops); err != nil { - return fmt.Errorf("failed to destroy database-operator in k8s-cluster: %w", err) - } - monitor.Info("Destroyed database-operator") - return nil - } -} diff --git a/operator/database/kinds/orb/zz_generated.deepcopy.go b/operator/database/kinds/orb/zz_generated.deepcopy.go deleted file mode 100644 index bf8af31d1b..0000000000 --- a/operator/database/kinds/orb/zz_generated.deepcopy.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !ignore_autogenerated - -/* - - -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. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package orb - -import ( - "k8s.io/api/core/v1" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Spec) DeepCopyInto(out *Spec) { - *out = *in - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]v1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. -func (in *Spec) DeepCopy() *Spec { - if in == nil { - return nil - } - out := new(Spec) - in.DeepCopyInto(out) - return out -} diff --git a/operator/database/takeoff.go b/operator/database/takeoff.go deleted file mode 100644 index b6763291c5..0000000000 --- a/operator/database/takeoff.go +++ /dev/null @@ -1,39 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" -) - -func Takeoff(monitor mntr.Monitor, gitClient *git.Client, adapt operator.AdaptFunc, k8sClient *kubernetes.Client) func() { - return func() { - internalMonitor := monitor.WithField("operator", "database") - internalMonitor.Info("Takeoff") - treeDesired, err := operator.Parse(gitClient, "database.yml") - if err != nil { - monitor.Error(err) - return - } - treeCurrent := &tree.Tree{} - - query, _, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) - if err != nil { - internalMonitor.Error(err) - return - } - - ensure, err := query(k8sClient, map[string]interface{}{}) - if err != nil { - internalMonitor.Error(err) - return - } - - if err := ensure(k8sClient); err != nil { - internalMonitor.Error(err) - return - } - } -} diff --git a/operator/helpers/intstr.go b/operator/helpers/intstr.go deleted file mode 100644 index f496381cf2..0000000000 --- a/operator/helpers/intstr.go +++ /dev/null @@ -1,13 +0,0 @@ -package helpers - -import "k8s.io/apimachinery/pkg/util/intstr" - -func IntToIntStr(value int) *intstr.IntOrString { - v := intstr.FromInt(value) - return &v -} - -func StringToIntStr(value string) *intstr.IntOrString { - v := intstr.FromString(value) - return &v -} diff --git a/operator/helpers/path.go b/operator/helpers/path.go deleted file mode 100644 index 13b3bbef1e..0000000000 --- a/operator/helpers/path.go +++ /dev/null @@ -1,17 +0,0 @@ -package helpers - -import ( - "os" - "strings" -) - -func PruneHome(pwd string) string { - if strings.HasPrefix(pwd, "~") { - userhome, err := os.UserHomeDir() - if err != nil { - panic(err) - } - pwd = userhome + pwd[1:] - } - return pwd -} diff --git a/operator/helpers/pointers.go b/operator/helpers/pointers.go deleted file mode 100644 index 49d6df6c57..0000000000 --- a/operator/helpers/pointers.go +++ /dev/null @@ -1,16 +0,0 @@ -package helpers - -func PointerInt32(value int32) *int32 { - pointer := value - return &pointer -} - -func PointerInt64(value int64) *int64 { - pointer := value - return &pointer -} - -func PointerBool(value bool) *bool { - pointer := value - return &pointer -} diff --git a/operator/secrets/secrets.go b/operator/secrets/secrets.go deleted file mode 100644 index 9234a259ca..0000000000 --- a/operator/secrets/secrets.go +++ /dev/null @@ -1,168 +0,0 @@ -package secrets - -import ( - "errors" - "fmt" - "strings" - - "github.com/caos/orbos/pkg/kubernetes" - - crddb "github.com/caos/zitadel/operator/api/database" - crdzit "github.com/caos/zitadel/operator/api/zitadel" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" - orbzit "github.com/caos/zitadel/operator/zitadel/kinds/orb" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/orb" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" -) - -const ( - zitadel string = "zitadel" - database string = "database" -) - -func GetAllSecretsFunc( - monitor mntr.Monitor, - printLogs, - gitops bool, - gitClient *git.Client, - k8sClient kubernetes.ClientInt, - orb *orb.Orb, -) func() ( - map[string]*secret.Secret, - map[string]*secret.Existing, - map[string]*tree.Tree, - error, -) { - return func() ( - map[string]*secret.Secret, - map[string]*secret.Existing, - map[string]*tree.Tree, - error, - ) { - return getAllSecrets(monitor, printLogs, gitops, orb, gitClient, k8sClient) - } -} - -func getAllSecrets( - monitor mntr.Monitor, - printLogs, - gitops bool, - orb *orb.Orb, - gitClient *git.Client, - k8sClient kubernetes.ClientInt, -) ( - map[string]*secret.Secret, - map[string]*secret.Existing, - map[string]*tree.Tree, - error, -) { - allSecrets := make(map[string]*secret.Secret, 0) - allExisting := make(map[string]*secret.Existing, 0) - allTrees := make(map[string]*tree.Tree, 0) - - if err := secret.GetOperatorSecrets( - monitor, - printLogs, - gitops, - gitClient, - git.ZitadelFile, - allTrees, - allSecrets, - allExisting, - func() (t *tree.Tree, err error) { return crdzit.ReadCrd(k8sClient) }, - func(t *tree.Tree) (map[string]*secret.Secret, map[string]*secret.Existing, bool, error) { - _, _, _, secrets, existing, migrate, err := orbzit.AdaptFunc(orb, "secret", nil, gitops, []string{})(monitor, t, &tree.Tree{}) - return secrets, existing, migrate, err - }, - ); err != nil { - return nil, nil, nil, err - } - - if err := secret.GetOperatorSecrets( - monitor, - printLogs, - gitops, - gitClient, - git.DatabaseFile, - allTrees, - allSecrets, - allExisting, - func() (t *tree.Tree, err error) { return crddb.ReadCrd(k8sClient) }, - func(t *tree.Tree) (map[string]*secret.Secret, map[string]*secret.Existing, bool, error) { - _, _, _, secrets, existing, migrate, err := orbdb.AdaptFunc("", nil, gitops, "database", "backup")(monitor, t, nil) - return secrets, existing, migrate, err - }, - ); err != nil { - return nil, nil, nil, err - } - - if k8sClient == nil { - allExisting = nil - } - - if len(allSecrets) == 0 && len(allExisting) == 0 { - return nil, nil, nil, mntr.ToUserError(errors.New("couldn't find any secrets")) - } - - return allSecrets, allExisting, allTrees, nil -} - -func PushFunc( - monitor mntr.Monitor, - gitops bool, - gitClient *git.Client, - k8sClient kubernetes.ClientInt, -) func( - trees map[string]*tree.Tree, - path string, -) error { - return func( - trees map[string]*tree.Tree, - path string, - ) error { - return push(monitor, gitops, gitClient, k8sClient, trees, path) - } -} - -func push( - monitor mntr.Monitor, - gitops bool, - gitClient *git.Client, - k8sClient kubernetes.ClientInt, - trees map[string]*tree.Tree, - path string, -) error { - - var ( - applyCRDFunc func(*tree.Tree) error - desiredFile git.DesiredFile - ) - - if strings.HasPrefix(path, zitadel) { - desiredFile = git.ZitadelFile - applyCRDFunc = func(t *tree.Tree) error { - return crdzit.WriteCrd(k8sClient, t) - } - } else if strings.HasPrefix(path, database) { - desiredFile = git.DatabaseFile - applyCRDFunc = func(t *tree.Tree) error { - return crddb.WriteCrd(k8sClient, t) - } - } else { - return errors.New("operator unknown") - } - - desired, found := trees[desiredFile.WOExtension()] - if !found { - return mntr.ToUserError(fmt.Errorf("desired state not found for %s", desiredFile.WOExtension())) - } - - if gitops { - return gitClient.PushDesiredFunc(desiredFile, desired)(monitor) - } - return applyCRDFunc(desired) -} diff --git a/operator/zitadel/destroy.go b/operator/zitadel/destroy.go deleted file mode 100644 index 870b60ebd9..0000000000 --- a/operator/zitadel/destroy.go +++ /dev/null @@ -1,34 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator" -) - -func Destroy( - monitor mntr.Monitor, - gitClient *git.Client, - adapt operator.AdaptFunc, - k8sClient *kubernetes.Client, -) error { - internalMonitor := monitor.WithField("operator", "zitadel") - internalMonitor.Info("Destroy") - treeDesired, err := operator.Parse(gitClient, "zitadel.yml") - if err != nil { - return err - } - treeCurrent := &tree.Tree{} - - _, destroy, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) - if err != nil { - return err - } - - if err := destroy(k8sClient); err != nil { - return err - } - return nil -} diff --git a/operator/zitadel/kinds/iam/iam.go b/operator/zitadel/kinds/iam/iam.go deleted file mode 100644 index 836d7e8a1f..0000000000 --- a/operator/zitadel/kinds/iam/iam.go +++ /dev/null @@ -1,64 +0,0 @@ -package iam - -import ( - "fmt" - - core "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -func Adapt( - monitor mntr.Monitor, - operatorLabels *labels.Operator, - desiredTree *tree.Tree, - currentTree *tree.Tree, - nodeselector map[string]string, - tolerations []core.Toleration, - dbClient database.Client, - namespace string, - action string, - version *string, - features []string, - customImageRegistry string, -) ( - query operator.QueryFunc, - destroy operator.DestroyFunc, - configure operator.ConfigureFunc, - secrets map[string]*secret.Secret, - existing map[string]*secret.Existing, - migrate bool, - err error, -) { - - defer func() { - if err != nil { - err = fmt.Errorf("adapting %s failed: %w", desiredTree.Common.Kind, err) - } - }() - - switch desiredTree.Common.Kind { - case "zitadel.caos.ch/ZITADEL": - apiLabels := labels.MustForAPI(operatorLabels, "ZITADEL", desiredTree.Common.Version()) - return zitadel.AdaptFunc( - apiLabels, - nodeselector, - tolerations, - dbClient, - namespace, - action, - version, - features, - customImageRegistry, - )(monitor, desiredTree, currentTree) - default: - return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown iam kind %s", desiredTree.Common.Kind)) - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/adapt.go b/operator/zitadel/kinds/iam/zitadel/adapt.go deleted file mode 100644 index b136ac71ac..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/adapt.go +++ /dev/null @@ -1,415 +0,0 @@ -package zitadel - -import ( - "errors" - "fmt" - "strconv" - "strings" - - "gopkg.in/yaml.v3" - core "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/helper" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/deployment" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/migration" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/services" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/setup" -) - -func AdaptFunc( - apiLabels *labels.API, - nodeselector map[string]string, - tolerations []core.Toleration, - dbClient database.Client, - namespace string, - action string, - version *string, - features []string, - customImageRegistry string, -) operator.AdaptFunc { - return func( - monitor mntr.Monitor, - desired *tree.Tree, - current *tree.Tree, - ) ( - operator.QueryFunc, - operator.DestroyFunc, - operator.ConfigureFunc, - map[string]*secret.Secret, - map[string]*secret.Existing, - bool, - error, - ) { - - internalMonitor := monitor.WithField("kind", "iam") - - desiredKind, err := parseDesiredV0(desired) - - _, _, sendAnalytics := mntr.Environment() - if sendAnalytics && - desiredKind != nil && - desiredKind.Spec != nil && - desiredKind.Spec.Configuration != nil && - desiredKind.Spec.Configuration.DNS != nil && - desiredKind.Spec.Configuration.DNS.Domain != "" { - monitor.SwitchEnvironment(strings.ToLower(strings.ReplaceAll(desiredKind.Spec.Configuration.DNS.Domain, ".", "-"))) - } - - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err) - } - desired.Parsed = desiredKind - - if err := desiredKind.Spec.validate(); err != nil { - return nil, nil, nil, nil, nil, false, err - } - - allSecrets, allExisting := getSecretsMap(desiredKind) - - if !monitor.IsVerbose() && desiredKind.Spec.Verbose { - internalMonitor.Verbose() - } - - // shared elements - cmName := "zitadel-vars" - secretName := "zitadel-secret" - consoleCMName := "console-config" - secretVarsName := "zitadel-secrets-vars" - secretPasswordName := "zitadel-passwords" - //paths which are used in the configuration and also are used for mounting the used files - certPath := "/home/zitadel/dbsecrets-zitadel" - secretPath := "/secret" - //services which are kubernetes resources and are used in the ambassador elements - grpcServiceName := "grpc-v1" - grpcPort := 80 - httpServiceName := "http-v1" - httpPort := 80 - uiServiceName := "ui-v1" - uiPort := 80 - usersWithoutPWs := getUserListWithoutPasswords(desiredKind) - - zitadelComponent := labels.MustForComponent(apiLabels, "ZITADEL") - zitadelDeploymentName := labels.MustForName(zitadelComponent, "zitadel") - zitadelPodSelector := labels.DeriveNameSelector(zitadelDeploymentName, false) - queryS, destroyS, err := services.AdaptFunc( - internalMonitor, - zitadelComponent, - zitadelPodSelector, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - getQueryC, destroyC, getConfigurationHashes, err := configuration.AdaptFunc( - internalMonitor, - zitadelComponent, - namespace, - desiredKind.Spec.Configuration, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordName, - dbClient, - services.GetClientIDFunc(namespace, httpServiceName, httpPort), - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryDB, err := database.AdaptFunc( - monitor, - dbClient, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryM, destroyM, err := migration.AdaptFunc( - internalMonitor, - labels.MustForComponent(apiLabels, "database"), - namespace, - action, - secretPasswordName, - migrationUser, - usersWithoutPWs, - nodeselector, - tolerations, - customImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - getQuerySetup, destroySetup, err := setup.AdaptFunc( - internalMonitor, - zitadelComponent, - namespace, - action, - desiredKind.Spec.NodeSelector, - desiredKind.Spec.Tolerations, - desiredKind.Spec.Resources, - version, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordName, - customImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryD, destroyD, err := deployment.AdaptFunc( - internalMonitor, - zitadelDeploymentName, - zitadelPodSelector, - desiredKind.Spec.Force, - version, - namespace, - desiredKind.Spec.ReplicaCount, - desiredKind.Spec.Affinity, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordName, - desiredKind.Spec.NodeSelector, - desiredKind.Spec.Tolerations, - desiredKind.Spec.Resources, - migration.GetDoneFunc(monitor, namespace, action), - configuration.GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName), - setup.GetDoneFunc(monitor, namespace, action), - customImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - queryAmbassador, destroyAmbassador, err := ambassador.AdaptFunc( - internalMonitor, - labels.MustForComponent(apiLabels, "apiGateway"), - namespace, - grpcServiceName+"."+namespace+":"+strconv.Itoa(grpcPort), - "http://"+httpServiceName+"."+namespace+":"+strconv.Itoa(httpPort), - "http://"+uiServiceName+"."+namespace, - desiredKind.Spec.Configuration.DNS, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - - destroyers := make([]operator.DestroyFunc, 0) - for _, feature := range features { - switch feature { - case "migration": - destroyers = append(destroyers, - destroyM, - ) - case "iam": - destroyers = append(destroyers, - destroyAmbassador, - destroyS, - destroyM, - destroyD, - destroySetup, - destroyC, - ) - } - } - - concatQueriers := func(queriers ...operator.QueryFunc) operator.QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (ensureFunc operator.EnsureFunc, err error) { - return operator.QueriersToEnsureFunc( - monitor, - true, - queriers, - k8sClient, - queried, - ) - } - } - - queryCfg := func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (ensureFunc operator.EnsureFunc, err error) { - users, err := getAllUsers(k8sClient, desiredKind) - if err != nil { - return nil, err - } - return concatQueriers( - queryDB, - getQueryC(users), - operator.EnsureFuncToQueryFunc(configuration.GetReadyFunc( - monitor, - namespace, - secretName, - secretVarsName, - secretPasswordName, - cmName, - consoleCMName, - )), - )(k8sClient, queried) - } - - queryReadyD := operator.EnsureFuncToQueryFunc(deployment.GetReadyFunc(monitor, namespace, zitadelDeploymentName)) - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - allZitadelUsers, err := getZitadelUserList(k8sClient, desiredKind) - if err != nil { - return nil, err - } - - queryReadyM := operator.EnsureFuncToQueryFunc(migration.GetDoneFunc(monitor, namespace, action)) - querySetup := getQuerySetup(allZitadelUsers, getConfigurationHashes) - queryReadySetup := operator.EnsureFuncToQueryFunc(setup.GetDoneFunc(monitor, namespace, action)) - queryD := queryD(allZitadelUsers, getConfigurationHashes) - - queriers := make([]operator.QueryFunc, 0) - for _, feature := range features { - switch feature { - case "migration": - queriers = append(queriers, - //configuration - queryCfg, - //migration - queryM, - queryReadyM, - operator.EnsureFuncToQueryFunc(migration.GetCleanupFunc(monitor, namespace, action)), - ) - case "iam": - queriers = append(queriers, - //configuration - queryCfg, - //migration - queryM, - queryReadyM, - //services - queryS, - //setup - querySetup, - queryReadySetup, - //deployment - queryD, - queryReadyD, - //handle change if necessary for clientID - queryCfg, - //again apply deployment if config changed - queryD, - queryReadyD, - //apply ambassador crds after zitadel is ready - queryAmbassador, - ) - case "scaledown": - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(deployment.GetScaleFunc(monitor, namespace, zitadelDeploymentName)(0)), - ) - case "scaleup": - queriers = append(queriers, - operator.EnsureFuncToQueryFunc(deployment.GetScaleFunc(monitor, namespace, zitadelDeploymentName)(desiredKind.Spec.ReplicaCount)), - ) - } - } - - return operator.QueriersToEnsureFunc(internalMonitor, true, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(monitor, destroyers), - func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, gitops bool) error { - - if desiredKind.Spec == nil { - desiredKind.Spec = &Spec{} - } - if desiredKind.Spec.Configuration == nil { - desiredKind.Spec.Configuration = &configuration.Configuration{} - } - if desiredKind.Spec.Configuration.Secrets == nil { - desiredKind.Spec.Configuration.Secrets = &configuration.Secrets{} - } - if desiredKind.Spec.Configuration.Secrets.CookieID == "" { - desiredKind.Spec.Configuration.Secrets.CookieID = "cookiekey_1" - } - if desiredKind.Spec.Configuration.Secrets.OTPVerificationID == "" { - desiredKind.Spec.Configuration.Secrets.OTPVerificationID = "otpverificationkey_1" - } - if desiredKind.Spec.Configuration.Secrets.DomainVerificationID == "" { - desiredKind.Spec.Configuration.Secrets.DomainVerificationID = "domainverificationkey_1" - } - if desiredKind.Spec.Configuration.Secrets.IDPConfigVerificationID == "" { - desiredKind.Spec.Configuration.Secrets.IDPConfigVerificationID = "idpconfigverificationkey_1" - } - if desiredKind.Spec.Configuration.Secrets.OIDCKeysID == "" { - desiredKind.Spec.Configuration.Secrets.OIDCKeysID = "oidckey_1" - } - if desiredKind.Spec.Configuration.Secrets.UserVerificationID == "" { - desiredKind.Spec.Configuration.Secrets.UserVerificationID = "userverificationkey_1" - } - if gitops && desiredKind.Spec.Configuration.Secrets.Keys == nil { - desiredKind.Spec.Configuration.Secrets.Keys = &secret.Secret{} - } - if !gitops && desiredKind.Spec.Configuration.Secrets.ExistingKeys == nil { - desiredKind.Spec.Configuration.Secrets.ExistingKeys = &secret.Existing{} - } - - keys := make(map[string]string) - if gitops { - if err := yaml.Unmarshal([]byte(desiredKind.Spec.Configuration.Secrets.Keys.Value), keys); err != nil { - return err - } - } else { - return errors.New("configure is not yet implemented for CRD mode") - } - - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.CookieID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.CookieID] = helper.RandStringBytes(32) - } - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.OTPVerificationID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.OTPVerificationID] = helper.RandStringBytes(32) - } - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.DomainVerificationID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.DomainVerificationID] = helper.RandStringBytes(32) - } - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.IDPConfigVerificationID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.IDPConfigVerificationID] = helper.RandStringBytes(32) - } - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.OIDCKeysID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.OIDCKeysID] = helper.RandStringBytes(32) - } - if _, ok := keys[desiredKind.Spec.Configuration.Secrets.UserVerificationID]; !ok { - keys[desiredKind.Spec.Configuration.Secrets.UserVerificationID] = helper.RandStringBytes(32) - } - - newKeys, err := yaml.Marshal(keys) - if err != nil { - return err - } - - desiredKind.Spec.Configuration.Secrets.Keys.Value = string(newKeys) - return nil - }, - allSecrets, - allExisting, - false, - nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/adapt.go b/operator/zitadel/kinds/iam/zitadel/ambassador/adapt.go deleted file mode 100644 index 02c7622896..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/adapt.go +++ /dev/null @@ -1,69 +0,0 @@ -package ambassador - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/grpc" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/hosts" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/http" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/ui" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - grpcURL string, - httpURL string, - uiURL string, - dns *configuration.DNS, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("type", "ambassador") - - queryGRPC, destroyGRPC, err := grpc.AdaptFunc(internalMonitor, componentLabels, namespace, grpcURL, dns) - if err != nil { - return nil, nil, err - } - - queryUI, destroyHTTP, err := ui.AdaptFunc(internalMonitor, componentLabels, namespace, uiURL, dns) - if err != nil { - return nil, nil, err - } - - queryHTTP, destroyUI, err := http.AdaptFunc(internalMonitor, componentLabels, namespace, httpURL, dns) - if err != nil { - return nil, nil, err - } - - queryHosts, destroyHosts, err := hosts.AdaptFunc(internalMonitor, componentLabels, namespace, dns) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - destroyGRPC, - destroyHTTP, - destroyUI, - destroyHosts, - } - - queriers := []operator.QueryFunc{ - queryHosts, - queryGRPC, - queryUI, - queryHTTP, - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(internalMonitor, true, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/ambassador/adapt_test.go deleted file mode 100644 index d38e78bb19..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/adapt_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package ambassador - -import ( - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/grpc" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/hosts" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/http" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador/ui" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func SetReturnResourceVersion( - k8sClient *kubernetesmock.MockClientInt, - group, - version, - kind, - namespace, - name string, - resourceVersion string, -) { - ret := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "annotations": map[string]interface{}{}, - "labels": map[string]interface{}{}, - "resourceVersion": resourceVersion, - }, - }, - } - k8sClient.EXPECT().GetNamespacedCRDResource(group, version, kind, namespace, name).MinTimes(1).MaxTimes(1).Return(ret, nil) -} - -func SetMappingsUI( - k8sClient *kubernetesmock.MockClientInt, - namespace string, -) { - group := "getambassador.io" - version := "v2" - kind := "Mapping" - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ui.AccountsName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ui.AccountsName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ui.ConsoleName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ui.ConsoleName, gomock.Any()).MinTimes(1).MaxTimes(1) -} - -func SetMappingsHTTP( - k8sClient *kubernetesmock.MockClientInt, - namespace string, -) { - group := "getambassador.io" - version := "v2" - kind := "Mapping" - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.AdminRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.AdminRName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.Upload, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.Upload, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.AuthorizeName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.AuthorizeName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.AuthRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.AuthRName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.EndsessionName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.EndsessionName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.IssuerName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.IssuerName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.MgmtName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.MgmtName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.OauthName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.OauthName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, http.OpenAPIName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, http.OpenAPIName, gomock.Any()).MinTimes(1).MaxTimes(1) -} - -func SetMappingsGRPC( - k8sClient *kubernetesmock.MockClientInt, - namespace string, -) { - group := "getambassador.io" - version := "v2" - kind := "Mapping" - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, grpc.AdminMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, grpc.AdminMName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, grpc.AuthMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, grpc.AuthMName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, grpc.MgmtMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, grpc.MgmtMName, gomock.Any()).MinTimes(1).MaxTimes(1) -} - -func SetHosts( - k8sClient *kubernetesmock.MockClientInt, - namespace string, -) { - group := "getambassador.io" - version := "v2" - kind := "Host" - k8sClient.EXPECT().CheckCRD("hosts.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, hosts.AccountsHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, hosts.AccountsHostName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, hosts.ApiHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, hosts.ApiHostName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, hosts.ConsoleHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, hosts.ConsoleHostName, gomock.Any()).MinTimes(1).MaxTimes(1) - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, hosts.IssuerHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, hosts.IssuerHostName, gomock.Any()).MinTimes(1).MaxTimes(1) - -} - -func TestAmbassador_Adapt(t *testing.T) { - - monitor := mntr.Monitor{} - namespace := "test" - grpcURL := "grpc" - httpURL := "http" - uiURL := "ui" - dns := &configuration.DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &configuration.Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - }, - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - SetMappingsUI(k8sClient, namespace) - SetMappingsHTTP(k8sClient, namespace) - SetMappingsGRPC(k8sClient, namespace) - SetHosts(k8sClient, namespace) - - query, _, err := AdaptFunc(monitor, mocklabels.Component, namespace, grpcURL, httpURL, uiURL, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt.go b/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt.go deleted file mode 100644 index 8cc66269e8..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt.go +++ /dev/null @@ -1,127 +0,0 @@ -package grpc - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/ambassador/mapping" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -const ( - AdminMName = "admin-grpc-v1" - AuthMName = "auth-grpc-v1" - MgmtMName = "mgmt-grpc-v1" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - grpcURL string, - dns *configuration.DNS, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("part", "grpc") - - destroyAdminG, err := mapping.AdaptFuncToDestroy(namespace, AdminMName) - if err != nil { - return nil, nil, err - } - destroyAuthG, err := mapping.AdaptFuncToDestroy(namespace, AuthMName) - if err != nil { - return nil, nil, err - } - destroyMgmtGRPC, err := mapping.AdaptFuncToDestroy(namespace, MgmtMName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyAdminG), - operator.ResourceDestroyToZitadelDestroy(destroyAuthG), - operator.ResourceDestroyToZitadelDestroy(destroyMgmtGRPC), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - crd, err := k8sClient.CheckCRD("mappings.getambassador.io") - if crd == nil || err != nil { - return func(k8sClient kubernetes.ClientInt) error { return nil }, nil - } - - apiDomain := dns.Subdomains.API + "." + dns.Domain - consoleDomain := dns.Subdomains.Console + "." + dns.Domain - _ = consoleDomain - - cors := &mapping.CORS{ - Origins: "*", - Methods: "POST, GET, OPTIONS, DELETE, PUT", - Headers: "*", - Credentials: true, - ExposedHeaders: "*", - MaxAge: "86400", - } - - queryAdminG, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AdminMName), - true, - apiDomain, - "/zitadel.admin.v1.AdminService/", - "", - grpcURL, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryAuthG, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AuthMName), - true, - apiDomain, - "/zitadel.auth.v1.AuthService/", - "", - grpcURL, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryMgmtGRPC, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, MgmtMName), - true, - apiDomain, - "/zitadel.management.v1.ManagementService/", - "", - grpcURL, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryAdminG), - operator.ResourceQueryToZitadelQuery(queryAuthG), - operator.ResourceQueryToZitadelQuery(queryMgmtGRPC), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt_test.go deleted file mode 100644 index 90db16a319..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/grpc/adapt_test.go +++ /dev/null @@ -1,268 +0,0 @@ -package grpc - -import ( - "testing" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func SetReturnResourceVersion( - k8sClient *kubernetesmock.MockClientInt, - group, - version, - kind, - namespace, - name string, - resourceVersion string, -) { - ret := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "resourceVersion": resourceVersion, - }, - }, - } - k8sClient.EXPECT().GetNamespacedCRDResource(group, version, kind, namespace, name).MinTimes(1).MaxTimes(1).Return(ret, nil) -} - -func TestGrpc_Adapt(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - url := "url" - dns := &configuration.DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &configuration.Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - }, - } - - componentLabels := mocklabels.Component - - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - cors := map[string]interface{}{ - "origins": "*", - "methods": "POST, GET, OPTIONS, DELETE, PUT", - "headers": "*", - "credentials": true, - "exposed_headers": "*", - "max_age": "86400", - } - adminMName := labels.MustForName(componentLabels, AdminMName) - adminM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(adminMName), - "name": adminMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/zitadel.admin.v1.AdminService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AdminMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AdminMName, adminM).MinTimes(1).MaxTimes(1) - - authMName := labels.MustForName(componentLabels, AuthMName) - authM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authMName), - "name": authMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/zitadel.auth.v1.AuthService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthMName, authM).MinTimes(1).MaxTimes(1) - - mgmtMName := labels.MustForName(componentLabels, MgmtMName) - mgmtM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(mgmtMName), - "name": mgmtMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/zitadel.management.v1.ManagementService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, MgmtMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, MgmtMName, mgmtM).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, url, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} - -func TestGrpc_Adapt2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - url := "url" - dns := &configuration.DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &configuration.Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - }, - } - - componentLabels := mocklabels.Component - - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - cors := map[string]interface{}{ - "origins": "*", - "methods": "POST, GET, OPTIONS, DELETE, PUT", - "headers": "*", - "credentials": true, - "exposed_headers": "*", - "max_age": "86400", - } - - adminMName := labels.MustForName(componentLabels, AdminMName) - adminM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(adminMName), - "name": adminMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/zitadel.admin.v1.AdminService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AdminMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AdminMName, adminM).MinTimes(1).MaxTimes(1) - - authMName := labels.MustForName(componentLabels, AuthMName) - authM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authMName), - "name": authMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/zitadel.auth.v1.AuthService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthMName, authM).MinTimes(1).MaxTimes(1) - - mgmtMName := labels.MustForName(componentLabels, MgmtMName) - mgmtM := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(mgmtMName), - "name": mgmtMName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/zitadel.management.v1.ManagementService/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - "grpc": true, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, MgmtMName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, MgmtMName, mgmtM).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, url, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt.go b/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt.go deleted file mode 100644 index 7dcfa83534..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt.go +++ /dev/null @@ -1,117 +0,0 @@ -package hosts - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/ambassador/host" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -const ( - AccountsHostName = "accounts" - ApiHostName = "api" - ConsoleHostName = "console" - IssuerHostName = "issuer" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - dns *configuration.DNS, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("part", "hosts") - - destroyAccounts, err := host.AdaptFuncToDestroy(namespace, AccountsHostName) - if err != nil { - return nil, nil, err - } - - destroyAPI, err := host.AdaptFuncToDestroy(namespace, ApiHostName) - if err != nil { - return nil, nil, err - } - - destroyConsole, err := host.AdaptFuncToDestroy(namespace, ConsoleHostName) - if err != nil { - return nil, nil, err - } - - destroyIssuer, err := host.AdaptFuncToDestroy(namespace, IssuerHostName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyAccounts), - operator.ResourceDestroyToZitadelDestroy(destroyAPI), - operator.ResourceDestroyToZitadelDestroy(destroyConsole), - operator.ResourceDestroyToZitadelDestroy(destroyIssuer), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - crd, err := k8sClient.CheckCRD("hosts.getambassador.io") - if crd == nil || err != nil { - return func(k8sClient kubernetes.ClientInt) error { return nil }, nil - } - - accountsDomain := dns.Subdomains.Accounts + "." + dns.Domain - apiDomain := dns.Subdomains.API + "." + dns.Domain - consoleDomain := dns.Subdomains.Console + "." + dns.Domain - issuerDomain := dns.Subdomains.Issuer + "." + dns.Domain - originCASecretName := dns.TlsSecret - authority := dns.ACMEAuthority - if authority == "" { - authority = "none" - } - - accountsSelector := map[string]string{ - "hostname": accountsDomain, - } - queryAccounts, err := host.AdaptFuncToEnsure(namespace, AccountsHostName, labels.MustForNameK8SMap(componentLabels, AccountsHostName), accountsDomain, authority, "", accountsSelector, originCASecretName) - if err != nil { - return nil, err - } - - apiSelector := map[string]string{ - "hostname": apiDomain, - } - queryAPI, err := host.AdaptFuncToEnsure(namespace, ApiHostName, labels.MustForNameK8SMap(componentLabels, ApiHostName), apiDomain, authority, "", apiSelector, originCASecretName) - if err != nil { - return nil, err - } - - consoleSelector := map[string]string{ - "hostname": consoleDomain, - } - queryConsole, err := host.AdaptFuncToEnsure(namespace, ConsoleHostName, labels.MustForNameK8SMap(componentLabels, ConsoleHostName), consoleDomain, authority, "", consoleSelector, originCASecretName) - if err != nil { - return nil, err - } - - issuerSelector := map[string]string{ - "hostname": issuerDomain, - } - queryIssuer, err := host.AdaptFuncToEnsure(namespace, IssuerHostName, labels.MustForNameK8SMap(componentLabels, IssuerHostName), issuerDomain, authority, "", issuerSelector, originCASecretName) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryAccounts), - operator.ResourceQueryToZitadelQuery(queryAPI), - operator.ResourceQueryToZitadelQuery(queryConsole), - operator.ResourceQueryToZitadelQuery(queryIssuer), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt_test.go deleted file mode 100644 index 80786263f3..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/hosts/adapt_test.go +++ /dev/null @@ -1,378 +0,0 @@ -package hosts - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/stretchr/testify/assert" - - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/golang/mock/gomock" - apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func SetReturnResourceVersion( - k8sClient *kubernetesmock.MockClientInt, - group, - version, - kind, - namespace, - name string, - resourceVersion string, -) { - ret := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "resourceVersion": resourceVersion, - }, - }, - } - k8sClient.EXPECT().GetNamespacedCRDResource(group, version, kind, namespace, name).MinTimes(1).MaxTimes(1).Return(ret, nil) -} - -func TestHosts_AdaptFunc(t *testing.T) { - - monitor := mntr.Monitor{} - namespace := "test" - dns := &configuration.DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &configuration.Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - }, - ACMEAuthority: "none", - } - - componentLabels := mocklabels.Component - - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("hosts.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Host" - - issuerHostName := labels.MustForName(componentLabels, IssuerHostName) - issuerHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": issuerHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(issuerHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": ".", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": ".", - }, - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, IssuerHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, IssuerHostName, issuerHost).MinTimes(1).MaxTimes(1) - - consoleHostName := labels.MustForName(componentLabels, ConsoleHostName) - consoleHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": consoleHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(consoleHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": ".", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": ".", - }, - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ConsoleHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ConsoleHostName, consoleHost).MinTimes(1).MaxTimes(1) - - apiHostName := labels.MustForName(componentLabels, ApiHostName) - apiHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": apiHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(apiHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": ".", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": ".", - }, - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ApiHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ApiHostName, apiHost).MinTimes(1).MaxTimes(1) - - accountsHostName := labels.MustForName(componentLabels, AccountsHostName) - accountsHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": accountsHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(accountsHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": ".", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": ".", - }, - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AccountsHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AccountsHostName, accountsHost).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} - -func TestHosts_AdaptFunc2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - dns := &configuration.DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &configuration.Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - }, - ACMEAuthority: "none", - } - - componentLabels := mocklabels.Component - - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("hosts.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Host" - - issuerHostName := labels.MustForName(componentLabels, IssuerHostName) - issuerHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": issuerHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(issuerHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": "issuer.domain", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": "issuer.domain", - }, - }, - "tlsSecret": map[string]interface{}{ - "name": "tls", - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, IssuerHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, IssuerHostName, issuerHost).MinTimes(1).MaxTimes(1) - - consoleHostName := labels.MustForName(componentLabels, ConsoleHostName) - consoleHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": consoleHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(consoleHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": "console.domain", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": "console.domain", - }, - }, - "tlsSecret": map[string]interface{}{ - "name": "tls", - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ConsoleHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ConsoleHostName, consoleHost).MinTimes(1).MaxTimes(1) - - apiHostName := labels.MustForName(componentLabels, ApiHostName) - apiHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": apiHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(apiHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": "api.domain", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": "api.domain", - }, - }, - "tlsSecret": map[string]interface{}{ - "name": "tls", - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ApiHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ApiHostName, apiHost).MinTimes(1).MaxTimes(1) - - accountsHostName := labels.MustForName(componentLabels, AccountsHostName) - accountsHost := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "kind": kind, - "apiVersion": group + "/" + version, - "metadata": map[string]interface{}{ - "name": accountsHostName.Name(), - "namespace": namespace, - "labels": toMapOfInterfaces(labels.MustK8sMap(accountsHostName)), - "annotations": map[string]interface{}{ - "aes_res_changed": "true", - }, - }, - "spec": map[string]interface{}{ - "hostname": "accounts.domain", - "acmeProvider": map[string]interface{}{ - "authority": "none", - }, - "ambassador_id": []interface{}{ - "default", - }, - "selector": map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "hostname": "accounts.domain", - }, - }, - "tlsSecret": map[string]interface{}{ - "name": "tls", - }, - }, - }} - - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AccountsHostName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AccountsHostName, accountsHost).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} - -func toMapOfInterfaces(m map[string]string) map[string]interface{} { - interfaces := make(map[string]interface{}) - for k, v := range m { - interfaces[k] = v - } - return interfaces -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt.go b/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt.go deleted file mode 100644 index 37dd7b20d3..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt.go +++ /dev/null @@ -1,274 +0,0 @@ -package http - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/ambassador/mapping" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -const ( - AdminRName = "admin-rest-v1" - Upload = "assets-v1" - MgmtName = "mgmt-v1" - OauthName = "oauth-v1" - AuthRName = "auth-rest-v1" - AuthorizeName = "authorize-v1" - EndsessionName = "endsession-v1" - IssuerName = "issuer-v1" - OpenAPIName = "openapi" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - httpUrl string, - dns *configuration.DNS, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("part", "http") - - destroyAdminR, err := mapping.AdaptFuncToDestroy(namespace, AdminRName) - if err != nil { - return nil, nil, err - } - - destroyUpload, err := mapping.AdaptFuncToDestroy(namespace, Upload) - if err != nil { - return nil, nil, err - } - - destroyMgmtRest, err := mapping.AdaptFuncToDestroy(namespace, MgmtName) - if err != nil { - return nil, nil, err - } - - destroyOAuthv2, err := mapping.AdaptFuncToDestroy(namespace, OauthName) - if err != nil { - return nil, nil, err - } - - destroyAuthR, err := mapping.AdaptFuncToDestroy(namespace, AuthRName) - if err != nil { - return nil, nil, err - } - - destroyAuthorize, err := mapping.AdaptFuncToDestroy(namespace, AuthorizeName) - if err != nil { - return nil, nil, err - } - - destroyEndsession, err := mapping.AdaptFuncToDestroy(namespace, EndsessionName) - if err != nil { - return nil, nil, err - } - - destroyIssuer, err := mapping.AdaptFuncToDestroy(namespace, IssuerName) - if err != nil { - return nil, nil, err - } - - destroySwagger, err := mapping.AdaptFuncToDestroy(namespace, OpenAPIName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyAdminR), - operator.ResourceDestroyToZitadelDestroy(destroyUpload), - operator.ResourceDestroyToZitadelDestroy(destroyMgmtRest), - operator.ResourceDestroyToZitadelDestroy(destroyOAuthv2), - operator.ResourceDestroyToZitadelDestroy(destroyAuthR), - operator.ResourceDestroyToZitadelDestroy(destroyAuthorize), - operator.ResourceDestroyToZitadelDestroy(destroyEndsession), - operator.ResourceDestroyToZitadelDestroy(destroyIssuer), - operator.ResourceDestroyToZitadelDestroy(destroySwagger), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - crd, err := k8sClient.CheckCRD("mappings.getambassador.io") - if crd == nil || err != nil { - return func(k8sClient kubernetes.ClientInt) error { return nil }, nil - } - - accountsDomain := dns.Subdomains.Accounts + "." + dns.Domain - apiDomain := dns.Subdomains.API + "." + dns.Domain - issuerDomain := dns.Subdomains.Issuer + "." + dns.Domain - - cors := &mapping.CORS{ - Origins: "*", - Methods: "POST, GET, OPTIONS, DELETE, PUT", - Headers: "*", - Credentials: true, - ExposedHeaders: "*", - MaxAge: "86400", - } - - queryAdminR, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AdminRName), - false, - apiDomain, - "/admin/v1", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryUpload, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, Upload), - false, - apiDomain, - "/assets/v1", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryMgmtRest, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, MgmtName), - false, - apiDomain, - "/management/v1/", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryOAuthv2, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, OauthName), - false, - apiDomain, - "/oauth/v2/", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryAuthR, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AuthRName), - false, - apiDomain, - "/auth/v1/", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryAuthorize, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AuthorizeName), - false, - accountsDomain, - "/oauth/v2/authorize", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryEndsession, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, EndsessionName), - false, - accountsDomain, - "/oauth/v2/endsession", - "", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryIssuer, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, IssuerName), - false, - issuerDomain, - "/.well-known/openid-configuration", - "/oauth/v2/.well-known/openid-configuration", - httpUrl, - 30000, - 30000, - cors, - ) - if err != nil { - return nil, err - } - - queryOpenAPI, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, OpenAPIName), - false, - apiDomain, - "/openapi/v2/swagger", - "", - httpUrl, - 30000, - 30000, - nil, - ) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryAdminR), - operator.ResourceQueryToZitadelQuery(queryUpload), - operator.ResourceQueryToZitadelQuery(queryMgmtRest), - operator.ResourceQueryToZitadelQuery(queryOAuthv2), - operator.ResourceQueryToZitadelQuery(queryAuthR), - operator.ResourceQueryToZitadelQuery(queryAuthorize), - operator.ResourceQueryToZitadelQuery(queryEndsession), - operator.ResourceQueryToZitadelQuery(queryIssuer), - operator.ResourceQueryToZitadelQuery(queryOpenAPI), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt_test.go deleted file mode 100644 index 61ac8cce13..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/http/adapt_test.go +++ /dev/null @@ -1,545 +0,0 @@ -package http - -import ( - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func SetReturnResourceVersion( - k8sClient *kubernetesmock.MockClientInt, - group, - version, - kind, - namespace, - name string, - resourceVersion string, -) { - ret := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "resourceVersion": resourceVersion, - }, - }, - } - k8sClient.EXPECT().GetNamespacedCRDResource(group, version, kind, namespace, name).MinTimes(1).MaxTimes(1).Return(ret, nil) -} - -func TestHttp_Adapt(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - url := "url" - dns := &configuration.DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &configuration.Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - }, - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - cors := map[string]interface{}{ - "origins": "*", - "methods": "POST, GET, OPTIONS, DELETE, PUT", - "headers": "*", - "credentials": true, - "exposed_headers": "*", - "max_age": "86400", - } - - componentLabels := mocklabels.Component - endSessionName := labels.MustForName(componentLabels, EndsessionName) - endsession := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(endSessionName), - "name": endSessionName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/oauth/v2/endsession", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, EndsessionName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, EndsessionName, endsession).MinTimes(1).MaxTimes(1) - - uploadName := labels.MustForName(componentLabels, Upload) - upload := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(uploadName), - "name": uploadName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/assets/v1", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, Upload, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, Upload, upload).MinTimes(1).MaxTimes(1) - - issuerName := labels.MustForName(componentLabels, IssuerName) - issuer := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(issuerName), - "name": issuerName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/.well-known/openid-configuration", - "rewrite": "/oauth/v2/.well-known/openid-configuration", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, IssuerName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, IssuerName, issuer).MinTimes(1).MaxTimes(1) - - authorizeName := labels.MustForName(componentLabels, AuthorizeName) - authorize := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authorizeName), - "name": authorizeName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/oauth/v2/authorize", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthorizeName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthorizeName, authorize).MinTimes(1).MaxTimes(1) - - oauthName := labels.MustForName(componentLabels, OauthName) - oauth := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(oauthName), - "name": oauthName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/oauth/v2/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, OauthName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, OauthName, oauth).MinTimes(1).MaxTimes(1) - - mgmtName := labels.MustForName(componentLabels, MgmtName) - mgmt := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(mgmtName), - "name": mgmtName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/management/v1/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, MgmtName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, MgmtName, mgmt).MinTimes(1).MaxTimes(1) - - adminRName := labels.MustForName(componentLabels, AdminRName) - adminR := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(adminRName), - "name": adminRName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/admin/v1", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AdminRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AdminRName, adminR).MinTimes(1).MaxTimes(1) - - authRName := labels.MustForName(componentLabels, AuthRName) - authR := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authRName), - "name": authRName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/auth/v1/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthRName, authR).MinTimes(1).MaxTimes(1) - - openAPIName := labels.MustForName(componentLabels, OpenAPIName) - openAPI := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(openAPIName), - "name": openAPIName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/openapi/v2/swagger", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, OpenAPIName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, OpenAPIName, openAPI).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, url, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} - -func TestHttp_Adapt2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - url := "url" - dns := &configuration.DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &configuration.Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - }, - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) - - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - cors := map[string]interface{}{ - "origins": "*", - "methods": "POST, GET, OPTIONS, DELETE, PUT", - "headers": "*", - "credentials": true, - "exposed_headers": "*", - "max_age": "86400", - } - - componentLabels := mocklabels.Component - - endsessionName := labels.MustForName(componentLabels, EndsessionName) - endsession := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(endsessionName), - "name": endsessionName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "accounts.domain", - "prefix": "/oauth/v2/endsession", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, EndsessionName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, EndsessionName, endsession).MinTimes(1).MaxTimes(1) - - uploadName := labels.MustForName(componentLabels, Upload) - upload := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(uploadName), - "name": uploadName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/assets/v1", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, Upload, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, Upload, upload).MinTimes(1).MaxTimes(1) - - issuerName := labels.MustForName(componentLabels, IssuerName) - issuer := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(issuerName), - "name": issuerName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "issuer.domain", - "prefix": "/.well-known/openid-configuration", - "rewrite": "/oauth/v2/.well-known/openid-configuration", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, IssuerName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, IssuerName, issuer).MinTimes(1).MaxTimes(1) - - authorizeName := labels.MustForName(componentLabels, AuthorizeName) - authorize := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authorizeName), - "name": authorizeName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "accounts.domain", - "prefix": "/oauth/v2/authorize", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthorizeName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthorizeName, authorize).MinTimes(1).MaxTimes(1) - - oauthName := labels.MustForName(componentLabels, OauthName) - oauth := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(oauthName), - "name": oauthName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/oauth/v2/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, OauthName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, OauthName, oauth).MinTimes(1).MaxTimes(1) - - mgmtName := labels.MustForName(componentLabels, MgmtName) - mgmt := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(mgmtName), - "name": mgmtName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/management/v1/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, MgmtName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, MgmtName, mgmt).MinTimes(1).MaxTimes(1) - - adminRName := labels.MustForName(componentLabels, AdminRName) - adminR := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(adminRName), - "name": adminRName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/admin/v1", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AdminRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AdminRName, adminR).MinTimes(1).MaxTimes(1) - - authRName := labels.MustForName(componentLabels, AuthRName) - authR := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(authRName), - "name": authRName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/auth/v1/", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - "cors": cors, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AuthRName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AuthRName, authR).MinTimes(1).MaxTimes(1) - - openAPIName := labels.MustForName(componentLabels, OpenAPIName) - openAPI := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(openAPIName), - "name": openAPIName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "api.domain", - "prefix": "/openapi/v2/swagger", - "rewrite": "", - "service": url, - "timeout_ms": 30000, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, OpenAPIName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, OpenAPIName, openAPI).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, url, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt.go b/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt.go deleted file mode 100644 index b2ed4a935e..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt.go +++ /dev/null @@ -1,95 +0,0 @@ -package ui - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/ambassador/mapping" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -const ( - ConsoleName = "console-v1" - AccountsName = "accounts-v1" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - uiURL string, - dns *configuration.DNS, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("part", "ui") - - destroyAcc, err := mapping.AdaptFuncToDestroy(namespace, AccountsName) - if err != nil { - return nil, nil, err - } - - destroyConsole, err := mapping.AdaptFuncToDestroy(namespace, ConsoleName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyAcc), - operator.ResourceDestroyToZitadelDestroy(destroyConsole), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - crd, err := k8sClient.CheckCRD("mappings.getambassador.io") - if crd == nil || err != nil { - return func(k8sClient kubernetes.ClientInt) error { return nil }, nil - } - - accountsDomain := dns.Subdomains.Accounts + "." + dns.Domain - consoleDomain := dns.Subdomains.Console + "." + dns.Domain - - queryConsole, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, ConsoleName), - false, - consoleDomain, - "/", - "/console/", - uiURL, - 0, - 0, - nil, - ) - if err != nil { - return nil, err - } - - queryAcc, err := mapping.AdaptFuncToEnsure( - namespace, - labels.MustForName(componentLabels, AccountsName), - false, - accountsDomain, - "/", - "/login/", - uiURL, - 30000, - 30000, - nil, - ) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryConsole), - operator.ResourceQueryToZitadelQuery(queryAcc), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt_test.go deleted file mode 100644 index d9d94e74de..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/ambassador/ui/adapt_test.go +++ /dev/null @@ -1,203 +0,0 @@ -package ui - -import ( - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func SetReturnResourceVersion( - k8sClient *kubernetesmock.MockClientInt, - group, - version, - kind, - namespace, - name string, - resourceVersion string, -) { - ret := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "metadata": map[string]interface{}{ - "resourceVersion": resourceVersion, - }, - }, - } - k8sClient.EXPECT().GetNamespacedCRDResource(group, version, kind, namespace, name).MinTimes(1).MaxTimes(1).Return(ret, nil) -} - -func SetCheckCRD(k8sClient *kubernetesmock.MockClientInt) { - k8sClient.EXPECT().CheckCRD("mappings.getambassador.io").MinTimes(1).MaxTimes(1).Return(&apixv1beta1.CustomResourceDefinition{}, nil) -} - -func SetMappingsEmpty( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - accountsLabels *labels.Name, - consoleLabels *labels.Name, - url string, -) { - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - accounts := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(accountsLabels), - "name": accountsLabels.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": ".", - "prefix": "/", - "rewrite": "/login/", - "service": url, - "timeout_ms": 30000, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, accountsLabels.Name(), "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, accountsLabels.Name(), accounts).MinTimes(1).MaxTimes(1) - - console := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(consoleLabels), - "name": consoleLabels.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "host": ".", - "prefix": "/", - "rewrite": "/console/", - "service": url, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, consoleLabels.Name(), "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, consoleLabels.Name(), console).MinTimes(1).MaxTimes(1) -} - -func TestUi_Adapt(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - uiURL := "url" - dns := &configuration.DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &configuration.Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - }, - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - componentLabels := mocklabels.Component - - SetCheckCRD(k8sClient) - SetMappingsEmpty( - k8sClient, - namespace, - labels.MustForName(componentLabels, AccountsName), - labels.MustForName(componentLabels, ConsoleName), - uiURL, - ) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, uiURL, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} - -func TestUi_Adapt2(t *testing.T) { - monitor := mntr.Monitor{} - namespace := "test" - uiURL := "url" - dns := &configuration.DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &configuration.Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - }, - } - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - SetCheckCRD(k8sClient) - - group := "getambassador.io" - version := "v2" - kind := "Mapping" - - componentLabels := mocklabels.Component - - accountsName := labels.MustForName(componentLabels, AccountsName) - accounts := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(accountsName), - "name": accountsName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "connect_timeout_ms": 30000, - "host": "accounts.domain", - "prefix": "/", - "rewrite": "/login/", - "service": uiURL, - "timeout_ms": 30000, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, AccountsName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, AccountsName, accounts).MinTimes(1).MaxTimes(1) - - consoleName := labels.MustForName(componentLabels, ConsoleName) - console := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": group + "/" + version, - "kind": kind, - "metadata": map[string]interface{}{ - "labels": labels.MustK8sMap(consoleName), - "name": consoleName.Name(), - "namespace": namespace, - }, - "spec": map[string]interface{}{ - "host": "console.domain", - "prefix": "/", - "rewrite": "/console/", - "service": uiURL, - }, - }, - } - SetReturnResourceVersion(k8sClient, group, version, kind, namespace, ConsoleName, "") - k8sClient.EXPECT().ApplyNamespacedCRDResource(group, version, kind, namespace, ConsoleName, console).MinTimes(1).MaxTimes(1) - - query, _, err := AdaptFunc(monitor, componentLabels, namespace, uiURL, dns) - assert.NoError(t, err) - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go b/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go deleted file mode 100644 index c995e66593..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/adapt.go +++ /dev/null @@ -1,212 +0,0 @@ -package configuration - -import ( - "time" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/configmap" - "github.com/caos/orbos/pkg/kubernetes/resources/secret" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration/users" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -type ConsoleEnv struct { - AuthServiceURL string `json:"authServiceUrl"` - MgmtServiceURL string `json:"mgmtServiceUrl"` - Issuer string `json:"issuer"` - ClientID string `json:"clientid"` - SubServiceURL string `json:"subscriptionServiceUrl"` - AssetServiceURL string `json:"assetServiceUrl"` -} - -const ( - googleServiceAccountJSONPath = "google-serviceaccount-key.json" - zitadelKeysPath = "zitadel-keys.yaml" - timeout = 60 * time.Second -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - desired *Configuration, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordName string, - dbClient database.Client, - getClientID func() string, -) ( - func( - necessaryUsers map[string]string, - ) operator.QueryFunc, - operator.DestroyFunc, - func( - k8sClient kubernetes.ClientInt, - queried map[string]interface{}, - necessaryUsers map[string]string, - ) (map[string]string, error), - error, -) { - internalMonitor := monitor.WithField("component", "configuration") - destroyCM, err := configmap.AdaptFuncToDestroy(namespace, cmName) - if err != nil { - return nil, nil, nil, err - } - destroyS, err := secret.AdaptFuncToDestroy(namespace, secretName) - if err != nil { - return nil, nil, nil, err - } - destroyCCM, err := configmap.AdaptFuncToDestroy(namespace, consoleCMName) - if err != nil { - return nil, nil, nil, err - } - destroySV, err := secret.AdaptFuncToDestroy(namespace, secretVarsName) - if err != nil { - return nil, nil, nil, err - } - destroySP, err := secret.AdaptFuncToDestroy(namespace, secretPasswordName) - if err != nil { - return nil, nil, nil, err - } - - _, destroyUser, err := users.AdaptFunc(internalMonitor, dbClient) - if err != nil { - return nil, nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - destroyUser, - operator.ResourceDestroyToZitadelDestroy(destroyS), - operator.ResourceDestroyToZitadelDestroy(destroyCM), - operator.ResourceDestroyToZitadelDestroy(destroyCCM), - operator.ResourceDestroyToZitadelDestroy(destroySV), - operator.ResourceDestroyToZitadelDestroy(destroySP), - } - - return func( - necessaryUsers map[string]string, - ) operator.QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - literalsSecret, err := literalsSecret(k8sClient, desired, googleServiceAccountJSONPath, zitadelKeysPath) - if err != nil { - return nil, err - } - literalsSecretVars, err := literalsSecretVars(k8sClient, desired) - if err != nil { - return nil, err - } - - queryUser, _, err := users.AdaptFunc(internalMonitor, dbClient) - if err != nil { - return nil, err - } - queryS, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, secretName), literalsSecret) - if err != nil { - return nil, err - } - querySV, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, secretVarsName), literalsSecretVars) - if err != nil { - return nil, err - } - querySP, err := secret.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, secretPasswordName), necessaryUsers) - if err != nil { - return nil, err - } - - queryCCM, err := configmap.AdaptFuncToEnsure( - namespace, - consoleCMName, - labels.MustForNameK8SMap(componentLabels, consoleCMName), - literalsConsoleCM( - getClientID(), - desired.DNS, - k8sClient, - namespace, - consoleCMName, - ), - ) - if err != nil { - return nil, err - } - - queryCM, err := configmap.AdaptFuncToEnsure( - namespace, - cmName, - labels.MustForNameK8SMap(componentLabels, cmName), - literalsConfigMap( - desired, - necessaryUsers, - certPath, - secretPath, - googleServiceAccountJSONPath, - zitadelKeysPath, - queried, - ), - ) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - queryUser(necessaryUsers), - operator.ResourceQueryToZitadelQuery(queryS), - operator.ResourceQueryToZitadelQuery(queryCCM), - operator.ResourceQueryToZitadelQuery(querySV), - operator.ResourceQueryToZitadelQuery(querySP), - operator.ResourceQueryToZitadelQuery(queryCM), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - } - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - func( - k8sClient kubernetes.ClientInt, - queried map[string]interface{}, - necessaryUsers map[string]string, - ) (map[string]string, error) { - literalsSecret, err := literalsSecret(k8sClient, desired, googleServiceAccountJSONPath, zitadelKeysPath) - if err != nil { - return nil, err - } - literalsSecretVars, err := literalsSecretVars(k8sClient, desired) - if err != nil { - return nil, err - } - - return map[string]string{ - secretName: getHash(literalsSecret), - secretVarsName: getHash(literalsSecretVars), - secretPasswordName: getHash(necessaryUsers), - cmName: getHash( - literalsConfigMap( - desired, - necessaryUsers, - certPath, - secretPath, - googleServiceAccountJSONPath, - zitadelKeysPath, - queried, - ), - ), - consoleCMName: getHash( - literalsConsoleCM( - getClientID(), - desired.DNS, - k8sClient, - namespace, - consoleCMName, - ), - ), - }, nil - }, - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/adapt_test.go deleted file mode 100644 index 504c1c72da..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/adapt_test.go +++ /dev/null @@ -1,340 +0,0 @@ -package configuration - -import ( - "errors" - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - databasemock "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func SetConfigMap( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - cmName string, - labels map[string]string, - queried map[string]interface{}, - desired *Configuration, - version *string, - users map[string]string, - certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath string, -) { - - k8sClient.EXPECT().ApplyConfigmap(&corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: cmName, - Labels: labels, - }, - Data: literalsConfigMap(desired, users, certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath, queried), - }) -} - -func SetSecretVars( - t *testing.T, - k8sClient *kubernetesmock.MockClientInt, - namespace string, - secretVarsName string, - labels map[string]string, - desired *Configuration, -) { - - literalsSV, err := literalsSecretVars(k8sClient, desired) - assert.NoError(t, err) - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: secretVarsName, - Labels: labels, - }, - Type: "Opaque", - StringData: literalsSV, - }).Times(1) -} -func SetConsoleCM( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - consoleCMName string, - labels map[string]string, - getClientID func() string, - desired *Configuration, -) { - - k8sClient.EXPECT().GetConfigMap(namespace, consoleCMName).Times(2).Return(nil, errors.New("Not Found")) - consoleCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: consoleCMName, - Labels: labels, - }, - Data: literalsConsoleCM(getClientID(), desired.DNS, k8sClient, namespace, consoleCMName), - } - k8sClient.EXPECT().ApplyConfigmap(consoleCM).Times(1) -} -func SetSecrets( - t *testing.T, - k8sClient *kubernetesmock.MockClientInt, - namespace string, - secretName string, - labels map[string]string, - desired *Configuration, -) { - literalsS, err := literalsSecret(k8sClient, desired, googleServiceAccountJSONPath, zitadelKeysPath) - assert.NoError(t, err) - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: secretName, - Labels: labels, - }, - Type: "Opaque", - StringData: literalsS, - }).Times(1) -} - -func SetSecretPasswords( - k8sClient *kubernetesmock.MockClientInt, - namespace string, - secretPasswordName string, - labels map[string]string, - users map[string]string, -) { - - k8sClient.EXPECT().ApplySecret(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: secretPasswordName, - Labels: labels, - }, - Type: "Opaque", - StringData: users, - }).Times(1) -} - -func TestConfiguration_Adapt(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - - monitor := mntr.Monitor{Fields: map[string]interface{}{"component": "configuration"}} - namespace := "test" - cmName := "cm" - secretName := "secret" - consoleCMName := "console" - secretVarsName := "vars" - secretPasswordName := "passwords" - getClientID := func() string { return "test" } - certPath := "test" - secretPath := "test" - version := "test" - users := map[string]string{ - "migration": "migration", - "management": "management", - "auth": "auth", - "authz": "authz", - "adminapi": "adminapi", - "notification": "notification", - "eventstore": "eventstore", - } - - componentLabels := mocklabels.Component - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "host", - Port: "port", - Users: []string{}, - }) - for user := range users { - dbClient.EXPECT().AddUser(monitor, user, k8sClient).Times(1) - } - - SetConfigMap( - k8sClient, - namespace, - cmName, - labels.MustForNameK8SMap(componentLabels, cmName), - queried, - desiredEmpty, - &version, - users, - certPath, - secretPath, - googleServiceAccountJSONPath, - zitadelKeysPath) - - SetSecretVars( - t, - k8sClient, - namespace, - secretVarsName, - labels.MustForNameK8SMap(componentLabels, secretVarsName), - desiredEmpty, - ) - - SetConsoleCM( - k8sClient, - namespace, - consoleCMName, - labels.MustForNameK8SMap(componentLabels, consoleCMName), - getClientID, - desiredEmpty, - ) - - SetSecrets( - t, - k8sClient, - namespace, - secretName, - labels.MustForNameK8SMap(componentLabels, secretName), - desiredEmpty, - ) - - SetSecretPasswords( - k8sClient, - namespace, - secretPasswordName, - labels.MustForNameK8SMap(componentLabels, secretPasswordName), - users, - ) - - getQuery, _, _, err := AdaptFunc( - monitor, - componentLabels, - namespace, - desiredEmpty, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordName, - dbClient, - getClientID, - ) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) - -} - -func TestConfiguration_AdaptFull(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - - monitor := mntr.Monitor{Fields: map[string]interface{}{"component": "configuration"}} - namespace := "test2" - cmName := "cm2" - secretName := "secret2" - consoleCMName := "console2" - secretVarsName := "vars2" - secretPasswordName := "passwords2" - getClientID := func() string { return "test2" } - certPath := "test2" - secretPath := "test2" - version := "test" - users := map[string]string{ - "migration": "migration", - "management": "management", - "auth": "auth", - "authz": "authz", - "adminapi": "adminapi", - "notification": "notification", - "eventstore": "eventstore", - } - - componentLabels := mocklabels.Component - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "host2", - Port: "port2", - Users: []string{}, - }) - for user := range users { - dbClient.EXPECT().AddUser(monitor, user, k8sClient).Times(1) - } - - SetConfigMap( - k8sClient, - namespace, - cmName, - labels.MustForNameK8SMap(componentLabels, cmName), - queried, - desiredFull, - &version, - users, - certPath, - secretPath, - googleServiceAccountJSONPath, - zitadelKeysPath) - - SetSecretVars( - t, - k8sClient, - namespace, - secretVarsName, - labels.MustForNameK8SMap(componentLabels, secretVarsName), - desiredFull, - ) - - SetConsoleCM( - k8sClient, - namespace, - consoleCMName, - labels.MustForNameK8SMap(componentLabels, consoleCMName), - getClientID, - desiredFull, - ) - - SetSecrets( - t, - k8sClient, - namespace, - secretName, - labels.MustForNameK8SMap(componentLabels, secretName), - desiredFull, - ) - - SetSecretPasswords( - k8sClient, - namespace, - secretPasswordName, - labels.MustForNameK8SMap(componentLabels, secretPasswordName), - users, - ) - - getQuery, _, _, err := AdaptFunc( - monitor, - componentLabels, - namespace, - desiredFull, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordName, - dbClient, - getClientID, - ) - - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) - -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/desired.go b/operator/zitadel/kinds/iam/zitadel/configuration/desired.go deleted file mode 100644 index 96fbd1a122..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/desired.go +++ /dev/null @@ -1,153 +0,0 @@ -package configuration - -import ( - "errors" - "fmt" - - "github.com/caos/orbos/pkg/secret" -) - -type Configuration struct { - Tracing *Tracing `yaml:"tracing,omitempty"` - Cache *Cache `yaml:"cache,omitempty"` - Secrets *Secrets `yaml:"secrets,omitempty"` - Notifications *Notifications `yaml:"notifications,omitempty"` - Passwords *Passwords `yaml:"passwords,omitempty"` - DebugMode bool `yaml:"debugMode"` - LogLevel string `yaml:"logLevel"` - MigrateEventStoreV1 bool `yaml:"migrateEventstoreV1"` - DNS *DNS `yaml:"dns"` - ClusterDNS string `yaml:"clusterdns"` - AssetStorage *AssetStorage `yaml:"assetStorage,omitempty"` - Proxy *Proxy `yaml:"proxy,omitempty"` -} - -func (c *Configuration) Validate() (err error) { - defer func() { - if err != nil { - err = fmt.Errorf("validating configuration failed: %w", err) - } - }() - - return c.DNS.validate() -} - -type AssetStorage struct { - Type string `yaml:"type,omitempty"` - Endpoint string `yaml:"endpoint,omitempty"` - AccessKeyID *secret.Secret `yaml:"accessKeyID,omitempty"` - ExistingAccessKeyID *secret.Existing `yaml:"existingAccessKeyID,omitempty"` - SecretAccessKey *secret.Secret `yaml:"secretAccessKey,omitempty"` - ExistingSecretAccessKey *secret.Existing `yaml:"ExistingSecretAccessKey,omitempty"` - SSL bool `yaml:"ssl,omitempty"` - Location string `yaml:"location,omitempty"` - BucketPrefix string `yaml:"bucketPrefix,omitempty"` - MultiDelete bool `yaml:"multiDelete,omitempty"` -} - -type DNS struct { - Domain string `yaml:"domain"` - TlsSecret string `yaml:"tlsSecret"` - ACMEAuthority string `yaml:"acmeAuthority"` - Subdomains *Subdomains `yaml:"subdomains"` -} - -func (d *DNS) validate() (err error) { - - defer func() { - if err != nil { - err = fmt.Errorf("validating dns failed: %w", err) - } - }() - - if d.TlsSecret != "" && d.ACMEAuthority != "none" && d.ACMEAuthority != "" { - return errors.New("if tls secret is provided, acme authority must be 'none'") - } - return nil -} - -type Subdomains struct { - Accounts string `yaml:"accounts"` - API string `yaml:"api"` - Console string `yaml:"console"` - Issuer string `yaml:"issuer"` - Subscription string `yaml:"subscription"` -} -type Passwords struct { - Migration *secret.Secret `yaml:"migration"` - Management *secret.Secret `yaml:"management"` - Auth *secret.Secret `yaml:"auth"` - Authz *secret.Secret `yaml:"authz"` - Adminapi *secret.Secret `yaml:"adminapi"` - Notification *secret.Secret `yaml:"notification"` - Eventstore *secret.Secret `yaml:"eventstore"` - Queries *secret.Secret `yaml:"queries"` - ExistingMigration *secret.Existing `yaml:"existingMigration"` - ExistingManagement *secret.Existing `yaml:"existingManagement"` - ExistingAuth *secret.Existing `yaml:"existingAuth"` - ExistingAuthz *secret.Existing `yaml:"existingAuthz"` - ExistingAdminapi *secret.Existing `yaml:"existingAdminapi"` - ExistingNotification *secret.Existing `yaml:"existingNotification"` - ExistingEventstore *secret.Existing `yaml:"existingEventstore"` - ExistingQueries *secret.Existing `yaml:"existingQueries"` -} - -type Secrets struct { - Keys *secret.Secret `yaml:"keys,omitempty"` - ExistingKeys *secret.Existing `yaml:"existingKeys,omitempty"` - UserVerificationID string `yaml:"userVerificationID,omitempty"` - OTPVerificationID string `yaml:"otpVerificationID,omitempty"` - OIDCKeysID string `yaml:"oidcKeysID,omitempty"` - CookieID string `yaml:"cookieID,omitempty"` - CSRFID string `yaml:"csrfID,omitempty"` - DomainVerificationID string `yaml:"domainVerificationID,omitempty"` - IDPConfigVerificationID string `yaml:"idpConfigVerificationID,omitempty"` -} - -type Notifications struct { - GoogleChatURL *secret.Secret `yaml:"googleChatURL,omitempty"` - ExistingGoogleChatURL *secret.Existing `yaml:"existingGoogleChatURL,omitempty"` - Email *Email `yaml:"email,omitempty"` - Twilio *Twilio `yaml:"twilio,omitempty"` -} - -type Tracing struct { - ServiceAccountJSON *secret.Secret `yaml:"serviceAccountJSON,omitempty"` - ExistingServiceAccountJSON *secret.Existing `yaml:"existingServiceAccountJSON,omitempty"` - ProjectID string `yaml:"projectID,omitempty"` - Fraction string `yaml:"fraction,omitempty"` - Type string `yaml:"type,omitempty"` -} - -type Twilio struct { - SenderName string `yaml:"senderName,omitempty"` - AuthToken *secret.Secret `yaml:"authToken,omitempty"` - SID *secret.Secret `yaml:"sid,omitempty"` - ExistingAuthToken *secret.Existing `yaml:"existingAuthToken,omitempty"` - ExistingSID *secret.Existing `yaml:"ExistingSid,omitempty"` -} - -type Email struct { - SMTPHost string `yaml:"smtpHost,omitempty"` - SMTPUser string `yaml:"smtpUser,omitempty"` - SenderAddress string `yaml:"senderAddress,omitempty"` - SenderName string `yaml:"senderName,omitempty"` - TLS bool `yaml:"tls,omitempty"` - AppKey *secret.Secret `yaml:"appKey,omitempty"` - ExistingAppKey *secret.Existing `yaml:"existingAppKey,omitempty"` -} - -type Cache struct { - MaxAge string `yaml:"maxAge,omitempty"` - SharedMaxAge string `yaml:"sharedMaxAge,omitempty"` - ShortMaxAge string `yaml:"shortMaxAge,omitempty"` - ShortSharedMaxAge string `yaml:"shortSharedMaxAge,omitempty"` -} - -type Proxy struct { - NoProxy []string `yaml:"noProxy,omitempty"` - HTTP *secret.Secret `yaml:"http,omitempty"` - HTTPS *secret.Secret `yaml:"https,omitempty"` - ExistingHTTP *secret.Existing `yaml:"existingHTTP,omitempty"` - ExistingHTTPS *secret.Existing `yaml:"existingHTTPS,omitempty"` -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/hash.go b/operator/zitadel/kinds/iam/zitadel/configuration/hash.go deleted file mode 100644 index 15e5cde483..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/hash.go +++ /dev/null @@ -1,16 +0,0 @@ -package configuration - -import ( - "crypto/sha512" - "encoding/base64" - "encoding/json" -) - -func getHash(dataMap map[string]string) string { - data, err := json.Marshal(dataMap) - if err != nil { - return "" - } - h := sha512.New() - return base64.URLEncoding.EncodeToString(h.Sum(data)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/literals.go b/operator/zitadel/kinds/iam/zitadel/configuration/literals.go deleted file mode 100644 index a36f357437..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/literals.go +++ /dev/null @@ -1,276 +0,0 @@ -package configuration - -import ( - "encoding/json" - "strconv" - "strings" - - "github.com/caos/orbos/mntr" - - "github.com/caos/orbos/pkg/secret/read" - - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -const ( - jsonName = "environment.json" -) - -func literalsConfigMap( - desired *Configuration, - users map[string]string, - certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath string, - queried map[string]interface{}, -) map[string]string { - - tls := "" - if desired.Notifications.Email.TLS { - tls = "TRUE" - } else { - tls = "FALSE" - } - - literalsConfigMap := map[string]string{ - "GOOGLE_APPLICATION_CREDENTIALS": secretPath + "/" + googleServiceAccountJSONPath, - "ZITADEL_KEY_PATH": secretPath + "/" + zitadelKeysPath, - "ZITADEL_LOG_LEVEL": "info", - "DEBUG_MODE": strconv.FormatBool(desired.DebugMode), - "ZITADEL_MIGRATE_ES_V1": strconv.FormatBool(desired.MigrateEventStoreV1), - "SMTP_TLS": tls, - "CAOS_OIDC_DEV": "true", - "CR_SSL_MODE": "require", - "CR_ROOT_CERT": certPath + "/ca.crt", - } - - if users != nil { - for user := range users { - literalsConfigMap["CR_"+strings.ToUpper(user)+"_CERT"] = certPath + "/client." + user + ".crt" - literalsConfigMap["CR_"+strings.ToUpper(user)+"_KEY"] = certPath + "/client." + user + ".key" - } - } - - if desired != nil { - if desired.Tracing != nil { - literalsConfigMap["ZITADEL_TRACING_PROJECT_ID"] = desired.Tracing.ProjectID - literalsConfigMap["ZITADEL_TRACING_FRACTION"] = desired.Tracing.Fraction - literalsConfigMap["ZITADEL_TRACING_TYPE"] = desired.Tracing.Type - } - if desired.Secrets != nil { - literalsConfigMap["ZITADEL_USER_VERIFICATION_KEY"] = desired.Secrets.UserVerificationID - literalsConfigMap["ZITADEL_OTP_VERIFICATION_KEY"] = desired.Secrets.OTPVerificationID - literalsConfigMap["ZITADEL_OIDC_KEYS_ID"] = desired.Secrets.OIDCKeysID - literalsConfigMap["ZITADEL_COOKIE_KEY"] = desired.Secrets.CookieID - literalsConfigMap["ZITADEL_CSRF_KEY"] = desired.Secrets.CSRFID - literalsConfigMap["ZITADEL_DOMAIN_VERIFICATION_KEY"] = desired.Secrets.DomainVerificationID - literalsConfigMap["ZITADEL_IDP_CONFIG_VERIFICATION_KEY"] = desired.Secrets.IDPConfigVerificationID - } - if desired.Notifications != nil { - literalsConfigMap["TWILIO_SENDER_NAME"] = desired.Notifications.Twilio.SenderName - literalsConfigMap["SMTP_HOST"] = desired.Notifications.Email.SMTPHost - literalsConfigMap["SMTP_USER"] = desired.Notifications.Email.SMTPUser - literalsConfigMap["EMAIL_SENDER_ADDRESS"] = desired.Notifications.Email.SenderAddress - literalsConfigMap["EMAIL_SENDER_NAME"] = desired.Notifications.Email.SenderName - } - if desired.Cache != nil { - literalsConfigMap["ZITADEL_CACHE_MAXAGE"] = desired.Cache.MaxAge - literalsConfigMap["ZITADEL_CACHE_SHARED_MAXAGE"] = desired.Cache.SharedMaxAge - literalsConfigMap["ZITADEL_SHORT_CACHE_MAXAGE"] = desired.Cache.ShortMaxAge - literalsConfigMap["ZITADEL_SHORT_CACHE_SHARED_MAXAGE"] = desired.Cache.ShortSharedMaxAge - } - - if desired.LogLevel != "" { - literalsConfigMap["ZITADEL_LOG_LEVEL"] = desired.LogLevel - } - - if desired.DNS != nil { - defaultDomain := desired.DNS.Domain - accountsDomain := desired.DNS.Subdomains.Accounts + "." + defaultDomain - accounts := "https://" + accountsDomain - issuer := "https://" + desired.DNS.Subdomains.Issuer + "." + defaultDomain - oauth := "https://" + desired.DNS.Subdomains.API + "." + defaultDomain + "/oauth/v2" - authorize := "https://" + desired.DNS.Subdomains.Accounts + "." + defaultDomain + "/oauth/v2" - console := "https://" + desired.DNS.Subdomains.Console + "." + defaultDomain - apiDomain := "https://" + desired.DNS.Subdomains.API + "." + defaultDomain - - literalsConfigMap["ZITADEL_ISSUER"] = issuer - literalsConfigMap["ZITADEL_ACCOUNTS"] = accounts - literalsConfigMap["ZITADEL_OAUTH"] = oauth - literalsConfigMap["ZITADEL_AUTHORIZE"] = authorize - literalsConfigMap["ZITADEL_CONSOLE"] = console - literalsConfigMap["ZITADEL_ACCOUNTS_DOMAIN"] = accountsDomain - literalsConfigMap["ZITADEL_COOKIE_DOMAIN"] = accountsDomain - literalsConfigMap["ZITADEL_DEFAULT_DOMAIN"] = defaultDomain - literalsConfigMap["ZITADEL_API_DOMAIN"] = apiDomain - } - if desired.AssetStorage != nil { - literalsConfigMap["ZITADEL_ASSET_STORAGE_TYPE"] = desired.AssetStorage.Type - literalsConfigMap["ZITADEL_ASSET_STORAGE_ENDPOINT"] = desired.AssetStorage.Endpoint - literalsConfigMap["ZITADEL_ASSET_STORAGE_SSL"] = strconv.FormatBool(desired.AssetStorage.SSL) - literalsConfigMap["ZITADEL_ASSET_STORAGE_LOCATION"] = desired.AssetStorage.Location - literalsConfigMap["ZITADEL_ASSET_STORAGE_BUCKET_PREFIX"] = desired.AssetStorage.BucketPrefix - literalsConfigMap["ZITADEL_ASSET_STORAGE_MULTI_DELETE"] = strconv.FormatBool(desired.AssetStorage.MultiDelete) - } - if desired.Proxy != nil { - literalsConfigMap["NO_PROXY"] = strings.Join(desired.Proxy.NoProxy, ",") - } - } - - sentryEnv, _, doIngest := mntr.Environment() - literalsConfigMap["SENTRY_ENVIRONMENT"] = sentryEnv - literalsConfigMap["SENTRY_USAGE"] = strconv.FormatBool(doIngest) - - db, err := database.GetDatabaseInQueried(queried) - if err == nil { - literalsConfigMap["ZITADEL_EVENTSTORE_HOST"] = db.Host - literalsConfigMap["ZITADEL_EVENTSTORE_PORT"] = db.Port - } - - return literalsConfigMap -} - -func literalsSecret(k8sClient kubernetes.ClientInt, desired *Configuration, googleServiceAccountJSONPath, zitadelKeysPath string) (map[string]string, error) { - literalsSecret := map[string]string{} - if desired != nil { - if desired.Tracing != nil && (desired.Tracing.ServiceAccountJSON != nil || desired.Tracing.ExistingServiceAccountJSON != nil) { - value, err := read.GetSecretValue(k8sClient, desired.Tracing.ServiceAccountJSON, desired.Tracing.ExistingServiceAccountJSON) - if err != nil { - return nil, err - } - literalsSecret[googleServiceAccountJSONPath] = value - } - if desired.Secrets != nil && (desired.Secrets.Keys != nil || desired.Secrets.ExistingKeys != nil) { - value, err := read.GetSecretValue(k8sClient, desired.Secrets.Keys, desired.Secrets.ExistingKeys) - if err != nil { - return nil, err - } - literalsSecret[zitadelKeysPath] = value - } - } - return literalsSecret, nil -} - -func literalsSecretVars(k8sClient kubernetes.ClientInt, desired *Configuration) (map[string]string, error) { - literalsSecretVars := map[string]string{} - if desired != nil { - if desired.Notifications != nil { - if desired.Notifications.Email.AppKey != nil || desired.Notifications.Email.ExistingAppKey != nil { - value, err := read.GetSecretValue(k8sClient, desired.Notifications.Email.AppKey, desired.Notifications.Email.ExistingAppKey) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_EMAILAPPKEY"] = value - } - if desired.Notifications.GoogleChatURL != nil || desired.Notifications.ExistingGoogleChatURL != nil { - value, err := read.GetSecretValue(k8sClient, desired.Notifications.GoogleChatURL, desired.Notifications.ExistingGoogleChatURL) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_GOOGLE_CHAT_URL"] = value - } - if desired.Notifications.Twilio.AuthToken != nil || desired.Notifications.Twilio.ExistingAuthToken != nil { - value, err := read.GetSecretValue(k8sClient, desired.Notifications.Twilio.AuthToken, desired.Notifications.Twilio.ExistingAuthToken) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_TWILIO_AUTH_TOKEN"] = value - } - if desired.Notifications.Twilio.SID != nil || desired.Notifications.Twilio.ExistingSID != nil { - value, err := read.GetSecretValue(k8sClient, desired.Notifications.Twilio.SID, desired.Notifications.Twilio.ExistingSID) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_TWILIO_SID"] = value - } - } - literalsSecretVars["ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID"] = "" - literalsSecretVars["ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY"] = "" - if desired.AssetStorage != nil { - as := desired.AssetStorage - if as.AccessKeyID != nil || as.ExistingAccessKeyID != nil { - value, err := read.GetSecretValue(k8sClient, as.AccessKeyID, as.ExistingAccessKeyID) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID"] = value - } - if as.SecretAccessKey != nil || as.ExistingSecretAccessKey != nil { - value, err := read.GetSecretValue(k8sClient, as.SecretAccessKey, as.ExistingSecretAccessKey) - if err != nil { - return nil, err - } - literalsSecretVars["ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY"] = value - } - } - literalsSecretVars["HTTP_PROXY"] = "" - literalsSecretVars["HTTPS_PROXY"] = "" - if desired.Proxy != nil { - if desired.Proxy.HTTP != nil || desired.Proxy.ExistingHTTP != nil { - value, err := read.GetSecretValue(k8sClient, desired.Proxy.HTTP, desired.Proxy.ExistingHTTP) - if err != nil { - return nil, err - } - literalsSecretVars["HTTP_PROXY"] = value - } - if desired.Proxy.HTTPS != nil || desired.Proxy.ExistingHTTPS != nil { - value, err := read.GetSecretValue(k8sClient, desired.Proxy.HTTPS, desired.Proxy.ExistingHTTPS) - if err != nil { - return nil, err - } - literalsSecretVars["HTTPS_PROXY"] = value - } - } - - _, dsns, doIngest := mntr.Environment() - zitadelDsn := "" - if doIngest { - zitadelDsn = dsns["zitadel"] - } - literalsSecretVars["SENTRY_DSN"] = zitadelDsn - } - return literalsSecretVars, nil -} - -func literalsConsoleCM( - clientID string, - dns *DNS, - k8sClient kubernetes.ClientInt, - namespace string, - cmName string, -) map[string]string { - literalsConsoleCM := map[string]string{} - consoleEnv := ConsoleEnv{ - ClientID: clientID, - } - - cm, err := k8sClient.GetConfigMap(namespace, cmName) - //only try to use the old CM when there is a CM found - if cm != nil && err == nil { - jsonData, ok := cm.Data[jsonName] - if ok { - literalsData := map[string]string{} - err := json.Unmarshal([]byte(jsonData), &literalsData) - if err == nil { - oldClientID, ok := literalsData["clientid"] - //only use the old ClientID if no new clientID is provided - if ok && consoleEnv.ClientID == "" { - consoleEnv.ClientID = oldClientID - } - } - } - } - - consoleEnv.Issuer = "https://" + dns.Subdomains.Issuer + "." + dns.Domain - consoleEnv.AuthServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain - consoleEnv.MgmtServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain - consoleEnv.SubServiceURL = "https://" + dns.Subdomains.Subscription + "." + dns.Domain - consoleEnv.AssetServiceURL = "https://" + dns.Subdomains.API + "." + dns.Domain - - data, err := json.Marshal(consoleEnv) - if err != nil { - return map[string]string{} - } - - literalsConsoleCM[jsonName] = string(data) - return literalsConsoleCM -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go deleted file mode 100644 index ba87cd2ed6..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/literals_test.go +++ /dev/null @@ -1,672 +0,0 @@ -package configuration - -import ( - "testing" - - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/secret" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -var ( - desiredEmpty = &Configuration{ - Tracing: &Tracing{ - ServiceAccountJSON: &secret.Secret{Value: ""}, - ProjectID: "", - Fraction: "", - Type: "", - }, - Secrets: &Secrets{ - Keys: &secret.Secret{Value: ""}, - UserVerificationID: "", - OTPVerificationID: "", - OIDCKeysID: "", - CookieID: "", - CSRFID: "", - DomainVerificationID: "", - IDPConfigVerificationID: "", - }, - Notifications: &Notifications{ - GoogleChatURL: &secret.Secret{Value: ""}, - Email: &Email{ - SMTPHost: "", - SMTPUser: "", - SenderAddress: "", - SenderName: "", - TLS: false, - AppKey: &secret.Secret{Value: ""}, - }, - Twilio: &Twilio{ - SenderName: "", - AuthToken: &secret.Secret{Value: ""}, - SID: &secret.Secret{Value: ""}, - }, - }, - Passwords: &Passwords{ - Migration: &secret.Secret{Value: ""}, - Management: &secret.Secret{Value: ""}, - Auth: &secret.Secret{Value: ""}, - Authz: &secret.Secret{Value: ""}, - Adminapi: &secret.Secret{Value: ""}, - Notification: &secret.Secret{Value: ""}, - Eventstore: &secret.Secret{Value: ""}, - }, - DebugMode: false, - LogLevel: "info", - DNS: &DNS{ - Domain: "", - TlsSecret: "", - Subdomains: &Subdomains{ - Accounts: "", - API: "", - Console: "", - Issuer: "", - Subscription: "", - }, - }, - AssetStorage: &AssetStorage{ - Type: "", - Endpoint: "", - AccessKeyID: &secret.Secret{Value: ""}, - ExistingAccessKeyID: nil, - SecretAccessKey: &secret.Secret{Value: ""}, - ExistingSecretAccessKey: nil, - SSL: false, - Location: "", - BucketPrefix: "", - }, - Proxy: &Proxy{ - NoProxy: nil, - HTTP: &secret.Secret{Value: ""}, - HTTPS: &secret.Secret{Value: ""}, - }, - ClusterDNS: "", - } - - desiredFull = &Configuration{ - Tracing: &Tracing{ - ServiceAccountJSON: &secret.Secret{Value: "sajson"}, - ProjectID: "projectid", - Fraction: "fraction", - Type: "type", - }, - Secrets: &Secrets{ - Keys: &secret.Secret{Value: "keys"}, - UserVerificationID: "userid", - OTPVerificationID: "otpid", - OIDCKeysID: "oidcid", - CookieID: "cookieid", - CSRFID: "csrfid", - DomainVerificationID: "domainid", - IDPConfigVerificationID: "idpid", - }, - Notifications: &Notifications{ - GoogleChatURL: &secret.Secret{Value: "chat"}, - Email: &Email{ - SMTPHost: "smtphost", - SMTPUser: "smtpuser", - SenderAddress: "sender", - SenderName: "sendername", - TLS: true, - AppKey: &secret.Secret{Value: "appkey"}, - }, - Twilio: &Twilio{ - SenderName: "sendername", - AuthToken: &secret.Secret{Value: "authtoken"}, - SID: &secret.Secret{Value: "sid"}, - }, - }, - Passwords: &Passwords{ - Migration: &secret.Secret{Value: "migration"}, - Management: &secret.Secret{Value: "management"}, - Auth: &secret.Secret{Value: "auth"}, - Authz: &secret.Secret{Value: "authz"}, - Adminapi: &secret.Secret{Value: "adminapi"}, - Notification: &secret.Secret{Value: "notification"}, - Eventstore: &secret.Secret{Value: "eventstore"}, - }, - DebugMode: true, - LogLevel: "debug", - DNS: &DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - Subscription: "sub", - }, - }, - ClusterDNS: "cluster", - AssetStorage: &AssetStorage{ - Type: "type", - Endpoint: "endpoint", - AccessKeyID: &secret.Secret{Value: "accesskeyid"}, - SecretAccessKey: &secret.Secret{Value: "secretaccesskey"}, - SSL: true, - Location: "location", - BucketPrefix: "bucketprefix", - }, - Proxy: &Proxy{ - NoProxy: []string{ - "test.com", - "10.0.0.0/16", - }, - HTTP: &secret.Secret{Value: "http://username:passwor@proxy:80"}, - HTTPS: &secret.Secret{Value: "https://username:passwor@proxy:443"}, - }, - } - desiredFullExisting = &Configuration{ - Tracing: &Tracing{ - ExistingServiceAccountJSON: &secret.Existing{"sajson", "sajson", "sajson"}, - ProjectID: "projectid", - Fraction: "fraction", - Type: "type", - }, - Secrets: &Secrets{ - ExistingKeys: &secret.Existing{"keys", "keys", "keys"}, - UserVerificationID: "userid", - OTPVerificationID: "otpid", - OIDCKeysID: "oidcid", - CookieID: "cookieid", - CSRFID: "csrfid", - DomainVerificationID: "domainid", - IDPConfigVerificationID: "idpid", - }, - Notifications: &Notifications{ - ExistingGoogleChatURL: &secret.Existing{"chat", "chat", "chat"}, - Email: &Email{ - SMTPHost: "smtphost", - SMTPUser: "smtpuser", - SenderAddress: "sender", - SenderName: "sendername", - TLS: true, - ExistingAppKey: &secret.Existing{"appkey", "appkey", "appkey"}, - }, - Twilio: &Twilio{ - SenderName: "sendername", - ExistingAuthToken: &secret.Existing{"migration", "migration", "migration"}, - ExistingSID: &secret.Existing{"sid", "sid", "sid"}, - }, - }, - Passwords: &Passwords{ - ExistingMigration: &secret.Existing{"migration", "migration", "migration"}, - ExistingEventstore: &secret.Existing{"eventstore", "eventstore", "eventstore"}, - ExistingNotification: &secret.Existing{"notification", "notification", "notification"}, - ExistingAuthz: &secret.Existing{"authz", "authz", "authz"}, - ExistingAuth: &secret.Existing{"auth", "auth", "auth"}, - ExistingAdminapi: &secret.Existing{"adminapi", "adminapi", "adminapi"}, - ExistingManagement: &secret.Existing{"management", "management", "management"}, - }, - DebugMode: true, - LogLevel: "debug", - DNS: &DNS{ - Domain: "domain", - TlsSecret: "tls", - Subdomains: &Subdomains{ - Accounts: "accounts", - API: "api", - Console: "console", - Issuer: "issuer", - Subscription: "sub", - }, - }, - ClusterDNS: "cluster", - AssetStorage: &AssetStorage{ - Type: "type", - Endpoint: "endpoint", - ExistingAccessKeyID: &secret.Existing{"accesskeyid", "accesskeyid", "accesskeyid"}, - ExistingSecretAccessKey: &secret.Existing{"secretaccesskey", "secretaccesskey", "secretaccesskey"}, - SSL: true, - Location: "location", - BucketPrefix: "bucketprefix", - }, - Proxy: &Proxy{ - NoProxy: []string{ - "test.com", - "10.0.0.0/16", - }, - ExistingHTTP: &secret.Existing{"httpproxy", "httpproxy", "httpproxy"}, - ExistingHTTPS: &secret.Existing{"httpsproxy", "httpsproxy", "httpsproxy"}, - }, - } -) - -func TestConfiguration_LiteralsConfigMap(t *testing.T) { - certPath := "test" - secretPath := "test" - googleSA := "test" - zitadelKeyPath := "test" - users := map[string]string{ - "migration": "migration", - "management": "management", - "auth": "auth", - "authz": "authz", - "adminapi": "adminapi", - "notification": "notification", - "eventstore": "eventstore", - } - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test"}, - }) - - equals := map[string]string{ - "ZITADEL_LOG_LEVEL": "info", - "CR_NOTIFICATION_KEY": "test/client.notification.key", - "CR_AUTHZ_KEY": "test/client.authz.key", - "ZITADEL_OTP_VERIFICATION_KEY": "", - "ZITADEL_COOKIE_KEY": "", - "SMTP_USER": "", - "EMAIL_SENDER_NAME": "", - "ZITADEL_COOKIE_DOMAIN": ".", - "ZITADEL_EVENTSTORE_HOST": "test", - "CR_ADMINAPI_CERT": "test/client.adminapi.crt", - "ZITADEL_IDP_CONFIG_VERIFICATION_KEY": "", - "ZITADEL_ACCOUNTS": "https://.", - "ZITADEL_OAUTH": "https://./oauth/v2", - "ZITADEL_EVENTSTORE_PORT": "test", - "SMTP_TLS": "FALSE", - "CR_ROOT_CERT": "test/ca.crt", - "CR_NOTIFICATION_CERT": "test/client.notification.crt", - "CR_EVENTSTORE_CERT": "test/client.eventstore.crt", - "ZITADEL_USER_VERIFICATION_KEY": "", - "ZITADEL_DEFAULT_DOMAIN": "", - "CR_SSL_MODE": "require", - "ZITADEL_KEY_PATH": "test/test", - "CR_MANAGEMENT_CERT": "test/client.management.crt", - "CR_AUTH_KEY": "test/client.auth.key", - "CR_AUTHZ_CERT": "test/client.authz.crt", - "CR_ADMINAPI_KEY": "test/client.adminapi.key", - "ZITADEL_TRACING_PROJECT_ID": "", - "ZITADEL_DOMAIN_VERIFICATION_KEY": "", - "CR_EVENTSTORE_KEY": "test/client.eventstore.key", - "ZITADEL_CSRF_KEY": "", - "TWILIO_SENDER_NAME": "", - "EMAIL_SENDER_ADDRESS": "", - "ZITADEL_ISSUER": "https://.", - "ZITADEL_CONSOLE": "https://.", - "ZITADEL_ACCOUNTS_DOMAIN": ".", - "ZITADEL_API_DOMAIN": "https://.", - "GOOGLE_APPLICATION_CREDENTIALS": "test/test", - "CR_MIGRATION_KEY": "test/client.migration.key", - "ZITADEL_TRACING_FRACTION": "", - "SMTP_HOST": "", - "CAOS_OIDC_DEV": "true", - "DEBUG_MODE": "false", - "ZITADEL_MIGRATE_ES_V1": "false", - "CR_AUTH_CERT": "test/client.auth.crt", - "ZITADEL_OIDC_KEYS_ID": "", - "CR_MIGRATION_CERT": "test/client.migration.crt", - "CR_MANAGEMENT_KEY": "test/client.management.key", - "ZITADEL_TRACING_TYPE": "", - "ZITADEL_AUTHORIZE": "https://./oauth/v2", - "ZITADEL_ASSET_STORAGE_TYPE": "", - "ZITADEL_ASSET_STORAGE_ENDPOINT": "", - "ZITADEL_ASSET_STORAGE_SSL": "false", - "ZITADEL_ASSET_STORAGE_LOCATION": "", - "ZITADEL_ASSET_STORAGE_BUCKET_PREFIX": "", - "ZITADEL_ASSET_STORAGE_MULTI_DELETE": "false", - "NO_PROXY": "", - "SENTRY_ENVIRONMENT": "", - "SENTRY_USAGE": "false", - } - - literals := literalsConfigMap(desiredEmpty, users, certPath, secretPath, googleSA, zitadelKeyPath, queried) - - assert.Equal(t, equals, literals) -} - -func TestConfiguration_LiteralsConfigMapFull(t *testing.T) { - certPath := "test" - secretPath := "test" - googleSA := "test" - zitadelKeyPath := "test" - users := map[string]string{ - "migration": "migration2", - "management": "management2", - "auth": "auth2", - "authz": "authz2", - "adminapi": "adminapi2", - "notification": "notification2", - "eventstore": "eventstore2", - } - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test"}, - }) - - equals := map[string]string{ - "CAOS_OIDC_DEV": "true", - "CR_ADMINAPI_CERT": "test/client.adminapi.crt", - "CR_ADMINAPI_KEY": "test/client.adminapi.key", - "CR_AUTHZ_CERT": "test/client.authz.crt", - "CR_AUTHZ_KEY": "test/client.authz.key", - "CR_AUTH_CERT": "test/client.auth.crt", - "CR_AUTH_KEY": "test/client.auth.key", - "CR_EVENTSTORE_CERT": "test/client.eventstore.crt", - "CR_EVENTSTORE_KEY": "test/client.eventstore.key", - "CR_MANAGEMENT_CERT": "test/client.management.crt", - "CR_MANAGEMENT_KEY": "test/client.management.key", - "CR_MIGRATION_CERT": "test/client.migration.crt", - "CR_MIGRATION_KEY": "test/client.migration.key", - "CR_NOTIFICATION_CERT": "test/client.notification.crt", - "CR_NOTIFICATION_KEY": "test/client.notification.key", - "CR_ROOT_CERT": "test/ca.crt", - "CR_SSL_MODE": "require", - "DEBUG_MODE": "true", - "EMAIL_SENDER_ADDRESS": "sender", - "EMAIL_SENDER_NAME": "sendername", - "GOOGLE_APPLICATION_CREDENTIALS": "test/test", - "SMTP_HOST": "smtphost", - "SMTP_TLS": "TRUE", - "SMTP_USER": "smtpuser", - "TWILIO_SENDER_NAME": "sendername", - "ZITADEL_ACCOUNTS": "https://accounts.domain", - "ZITADEL_ACCOUNTS_DOMAIN": "accounts.domain", - "ZITADEL_AUTHORIZE": "https://accounts.domain/oauth/v2", - "ZITADEL_CONSOLE": "https://console.domain", - "ZITADEL_API_DOMAIN": "https://api.domain", - "ZITADEL_COOKIE_DOMAIN": "accounts.domain", - "ZITADEL_COOKIE_KEY": "cookieid", - "ZITADEL_CSRF_KEY": "csrfid", - "ZITADEL_DEFAULT_DOMAIN": "domain", - "ZITADEL_DOMAIN_VERIFICATION_KEY": "domainid", - "ZITADEL_EVENTSTORE_HOST": "test", - "ZITADEL_EVENTSTORE_PORT": "test", - "ZITADEL_IDP_CONFIG_VERIFICATION_KEY": "idpid", - "ZITADEL_ISSUER": "https://issuer.domain", - "ZITADEL_KEY_PATH": "test/test", - "ZITADEL_LOG_LEVEL": "debug", - "ZITADEL_MIGRATE_ES_V1": "false", - "ZITADEL_OAUTH": "https://api.domain/oauth/v2", - "ZITADEL_OIDC_KEYS_ID": "oidcid", - "ZITADEL_OTP_VERIFICATION_KEY": "otpid", - "ZITADEL_TRACING_FRACTION": "fraction", - "ZITADEL_TRACING_PROJECT_ID": "projectid", - "ZITADEL_TRACING_TYPE": "type", - "ZITADEL_USER_VERIFICATION_KEY": "userid", - "ZITADEL_ASSET_STORAGE_TYPE": "type", - "ZITADEL_ASSET_STORAGE_ENDPOINT": "endpoint", - "ZITADEL_ASSET_STORAGE_SSL": "true", - "ZITADEL_ASSET_STORAGE_LOCATION": "location", - "ZITADEL_ASSET_STORAGE_BUCKET_PREFIX": "bucketprefix", - "ZITADEL_ASSET_STORAGE_MULTI_DELETE": "false", - "NO_PROXY": "test.com,10.0.0.0/16", - "SENTRY_ENVIRONMENT": "", - "SENTRY_USAGE": "false", - } - literals := literalsConfigMap(desiredFull, users, certPath, secretPath, googleSA, zitadelKeyPath, queried) - - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecrets(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - googleSA := "sajson" - zitadelKeyPath := "zitadel" - - equals := map[string]string{ - googleSA: "", - zitadelKeyPath: "", - } - - literals, err := literalsSecret(client, desiredEmpty, googleSA, zitadelKeyPath) - assert.NoError(t, err) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecretsFull(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - googleSA := "sajson" - zitadelKeyPath := "zitadel" - - equals := map[string]string{ - googleSA: "sajson", - zitadelKeyPath: "keys", - } - - literals, err := literalsSecret(client, desiredFull, googleSA, zitadelKeyPath) - assert.NoError(t, err) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecretsExisting(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - sajson := "sajson" - keys := "keys" - namespace := "caos-system" - client.EXPECT().GetSecret(namespace, desiredFullExisting.Tracing.ExistingServiceAccountJSON.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Tracing.ExistingServiceAccountJSON.Key: sajson, - }, - Data: map[string][]byte{ - desiredFullExisting.Tracing.ExistingServiceAccountJSON.Key: []byte(sajson), - }, - }, nil) - client.EXPECT().GetSecret(namespace, desiredFullExisting.Secrets.ExistingKeys.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Secrets.ExistingKeys.Key: keys, - }, - Data: map[string][]byte{ - desiredFullExisting.Secrets.ExistingKeys.Key: []byte(keys), - }, - }, nil) - googleSA := "sajson" - zitadelKeyPath := "zitadel" - - equals := map[string]string{ - googleSA: sajson, - zitadelKeyPath: keys, - } - - literals, err := literalsSecret(client, desiredFullExisting, googleSA, zitadelKeyPath) - assert.NoError(t, err) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecretVars(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - equals := map[string]string{ - "ZITADEL_EMAILAPPKEY": "", - "ZITADEL_GOOGLE_CHAT_URL": "", - "ZITADEL_TWILIO_AUTH_TOKEN": "", - "ZITADEL_TWILIO_SID": "", - "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": "", - "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": "", - "HTTPS_PROXY": "", - "HTTP_PROXY": "", - "SENTRY_DSN": "", - } - literals, err := literalsSecretVars(client, desiredEmpty) - assert.NoError(t, err) - - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecretVarsFull(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - equals := map[string]string{ - "ZITADEL_EMAILAPPKEY": "appkey", - "ZITADEL_GOOGLE_CHAT_URL": "chat", - "ZITADEL_TWILIO_AUTH_TOKEN": "authtoken", - "ZITADEL_TWILIO_SID": "sid", - "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": "accesskeyid", - "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": "secretaccesskey", - "HTTP_PROXY": "http://username:passwor@proxy:80", - "HTTPS_PROXY": "https://username:passwor@proxy:443", - "SENTRY_DSN": "", - } - literals, err := literalsSecretVars(client, desiredFull) - - assert.NoError(t, err) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsSecretVarsExisting(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - // namespace := "caos-system" - appkey := "appkey" - chat := "chat" - authtoken := "authtoken" - sid := "sid" - akid := "accesskeyid" - sak := "secretaccesskey" - httpProxy := "http://username:passwor@proxy:80" - httpsProxy := "https://username:passwor@proxy:443" - /* TODO: incomment!!! - client.EXPECT().GetSecret(namespace, desiredFullExisting.Notifications.Email.ExistingAppKey.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Notifications.Email.ExistingAppKey.Key: appkey, - }, - Data: map[string][]byte{ - desiredFullExisting.Notifications.Email.ExistingAppKey.Key: []byte(appkey), - }, - }, nil) - client.EXPECT().GetSecret(namespace, desiredFullExisting.Notifications.ExistingGoogleChatURL.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Notifications.ExistingGoogleChatURL.Key: chat, - }, - Data: map[string][]byte{ - desiredFullExisting.Notifications.ExistingGoogleChatURL.Key: []byte(chat), - }, - }, nil) - client.EXPECT().GetSecret(namespace, desiredFullExisting.Notifications.Twilio.ExistingAuthToken.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Notifications.Twilio.ExistingAuthToken.Key: authtoken, - }, - Data: map[string][]byte{ - desiredFullExisting.Notifications.Twilio.ExistingAuthToken.Key: []byte(authtoken), - }, - }, nil) - client.EXPECT().GetSecret(namespace, desiredFullExisting.Notifications.Twilio.ExistingSID.Name).Return(&corev1.Secret{ - StringData: map[string]string{ - desiredFullExisting.Notifications.Twilio.ExistingSID.Key: sid, - }, - Data: map[string][]byte{ - desiredFullExisting.Notifications.Twilio.ExistingSID.Key: []byte(sid), - }, - }, nil) - */ - equals := map[string]string{ - "ZITADEL_EMAILAPPKEY": appkey, - "ZITADEL_GOOGLE_CHAT_URL": chat, - "ZITADEL_TWILIO_AUTH_TOKEN": authtoken, - "ZITADEL_TWILIO_SID": sid, - "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": akid, - "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": sak, - "HTTP_PROXY": httpProxy, - "HTTPS_PROXY": httpsProxy, - "SENTRY_DSN": "", - } - literals, err := literalsSecretVars(client, desiredFull) - - assert.NoError(t, err) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsConsoleCM(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - clientID := "" - namespace := "test" - cmName := "cm" - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: cmName, - }, - Data: map[string]string{"environment.json": "{\"authServiceUrl\":\"https://.\",\"mgmtServiceUrl\":\"https://.\",\"issuer\":\"https://.\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://.\"}"}, - } - - equals := map[string]string{"environment.json": "{\"authServiceUrl\":\"https://.\",\"mgmtServiceUrl\":\"https://.\",\"issuer\":\"https://.\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://.\",\"assetServiceUrl\":\"https://.\"}"} - k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) - - literals := literalsConsoleCM(clientID, desiredEmpty.DNS, k8sClient, namespace, cmName) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsConsoleCMFull(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - clientID := "test" - namespace := "test" - cmName := "cm" - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: cmName, - }, - Data: map[string]string{}, - } - - equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", - } - k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) - - literals := literalsConsoleCM(clientID, desiredFull.DNS, k8sClient, namespace, cmName) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsConsoleCMWithCM(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - clientID := "test" - namespace := "test" - cmName := "cm" - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: cmName, - }, - Data: map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", - }, - } - - equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", - } - k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) - - literals := literalsConsoleCM(clientID, desiredFull.DNS, k8sClient, namespace, cmName) - assert.EqualValues(t, equals, literals) -} - -func TestConfiguration_LiteralsConsoleCMWithCMFull(t *testing.T) { - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - clientID := "" - namespace := "test" - cmName := "cm" - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: cmName, - }, - Data: map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", - }, - } - - equals := map[string]string{ - "environment.json": "{\"authServiceUrl\":\"https://api.domain\",\"mgmtServiceUrl\":\"https://api.domain\",\"issuer\":\"https://issuer.domain\",\"clientid\":\"test\",\"subscriptionServiceUrl\":\"https://sub.domain\",\"assetServiceUrl\":\"https://api.domain\"}", - } - k8sClient.EXPECT().GetConfigMap(namespace, cmName).Times(1).Return(cm, nil) - - literals := literalsConsoleCM(clientID, desiredFull.DNS, k8sClient, namespace, cmName) - assert.EqualValues(t, equals, literals) -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/ready.go b/operator/zitadel/kinds/iam/zitadel/configuration/ready.go deleted file mode 100644 index 1397212318..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/ready.go +++ /dev/null @@ -1,43 +0,0 @@ -package configuration - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" -) - -func GetReadyFunc( - monitor mntr.Monitor, - namespace string, - secretName string, - secretVarsName string, - secretPasswordName string, - cmName string, - consoleCMName string, -) func(k8sClient kubernetes.ClientInt) error { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Debug("Waiting for configuration to be created") - if err := k8sClient.WaitForSecret(namespace, secretName, timeout); err != nil { - return fmt.Errorf("error while waiting for secret: %w", err) - } - - if err := k8sClient.WaitForSecret(namespace, secretVarsName, timeout); err != nil { - return fmt.Errorf("error while waiting for vars secret: %w", err) - } - - if err := k8sClient.WaitForSecret(namespace, secretPasswordName, timeout); err != nil { - return fmt.Errorf("error while waiting for password secret: %w", err) - } - - if err := k8sClient.WaitForConfigMap(namespace, cmName, timeout); err != nil { - return fmt.Errorf("error while waiting for configmap: %w", err) - } - - if err := k8sClient.WaitForConfigMap(namespace, consoleCMName, timeout); err != nil { - return fmt.Errorf("error while waiting for console configmap: %w", err) - } - monitor.Debug("configuration is created") - return nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/ready_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/ready_test.go deleted file mode 100644 index b1f2df7989..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/ready_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package configuration - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestConfiguration_Ready1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.NoError(t, readyFunc(client)) -} - -func TestConfiguration_Ready2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - secretName := "testSecret2" - secretVarsName := "testVars2" - secretPasswordName := "testPasswords2" - cmName := "testCM2" - consoleCMName := "testConsole2" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.NoError(t, readyFunc(client)) -} - -func TestConfiguration_ReadyFail1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(errors.New("fail")) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} - -func TestConfiguration_ReadyFail2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(errors.New("fail")) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} - -func TestConfiguration_ReadyFail3(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(errors.New("fail")) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} - -func TestConfiguration_ReadyFail4(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(errors.New("fail")) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} - -func TestConfiguration_ReadyFail5(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - secretName := "testSecret" - secretVarsName := "testVars" - secretPasswordName := "testPasswords" - cmName := "testCM" - consoleCMName := "testConsole" - - client.EXPECT().WaitForConfigMap(namespace, cmName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForConfigMap(namespace, consoleCMName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretVarsName, timeout).MinTimes(1).MaxTimes(1).Return(nil) - client.EXPECT().WaitForSecret(namespace, secretPasswordName, timeout).MinTimes(1).MaxTimes(1).Return(errors.New("fail")) - - readyFunc := GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt.go b/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt.go deleted file mode 100644 index 8b8a50c21d..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt.go +++ /dev/null @@ -1,70 +0,0 @@ -package users - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -func AdaptFunc( - monitor mntr.Monitor, - dbClient database.Client, -) ( - func(users map[string]string) operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("component", "db-users") - - destroyers := make([]operator.DestroyFunc, 0) - - destroyers = append(destroyers, func(k8sClient kubernetes.ClientInt) error { - list, err := dbClient.ListUsers(internalMonitor, k8sClient) - if err != nil { - return err - } - for _, listedUser := range list { - if err := dbClient.DeleteUser(internalMonitor, listedUser, k8sClient); err != nil { - return err - } - } - return nil - }) - - return func(users map[string]string) operator.QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - queriers := make([]operator.QueryFunc, 0) - db, err := database.GetDatabaseInQueried(queried) - if err != nil { - return nil, err - } - - usernames := []string{} - for username := range users { - usernames = append(usernames, username) - } - - for _, username := range usernames { - ensure := createIfNecessary(monitor, username, db.Users, dbClient) - if ensure != nil { - queriers = append(queriers, operator.EnsureFuncToQueryFunc(ensure)) - } - } - - for _, listedUser := range db.Users { - ensure := deleteIfNotRequired(monitor, listedUser, usernames, dbClient) - if ensure != nil { - queriers = append(queriers, operator.EnsureFuncToQueryFunc(ensure)) - } - } - - if queriers == nil || len(queriers) == 0 { - return func(k8sClient kubernetes.ClientInt) error { return nil }, nil - } - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - } - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt_test.go deleted file mode 100644 index 8e9c69919d..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/users/adapt_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package users - -import ( - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - databasemock "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestUsers_Adapt_CreateFirst(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - users := map[string]string{"test": "testpw"} - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - monitor := mntr.Monitor{} - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{}, - }) - dbClient.EXPECT().AddUser(monitor, "test", client) - - getQuery, _, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(client, queried) - assert.NoError(t, err) - err = ensure(client) - assert.NoError(t, err) -} - -func TestUsers_Adapt_DoNothing(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - users := map[string]string{"test": "testpw"} - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - monitor := mntr.Monitor{} - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test"}, - }) - - getQuery, _, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestUsers_Adapt_Add(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - users := map[string]string{"test": "testpw", "test2": "testpw"} - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - monitor := mntr.Monitor{} - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test"}, - }) - dbClient.EXPECT().AddUser(monitor, "test2", client) - - getQuery, _, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(client, queried) - assert.NoError(t, err) - err = ensure(client) - assert.NoError(t, err) -} - -func TestUsers_Adapt_Delete(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - users := map[string]string{"test": "testpw", "test2": "testpw"} - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - monitor := mntr.Monitor{} - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test", "test2", "test3"}, - }) - - dbClient.EXPECT().DeleteUser(monitor, "test3", client) - - getQuery, _, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(client, queried) - err = ensure(client) - assert.NoError(t, err) -} - -func TestUsers_Adapt_DeleteMultiple(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - users := map[string]string{} - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - monitor := mntr.Monitor{} - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: "test", - Port: "test", - Users: []string{"test", "test2", "test3"}, - }) - - dbClient.EXPECT().DeleteUser(monitor, "test", client) - dbClient.EXPECT().DeleteUser(monitor, "test2", client) - dbClient.EXPECT().DeleteUser(monitor, "test3", client) - - getQuery, _, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - query := getQuery(users) - ensure, err := query(client, queried) - err = ensure(client) - assert.NoError(t, err) -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/users/users.go b/operator/zitadel/kinds/iam/zitadel/configuration/users/users.go deleted file mode 100644 index e2672059ba..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/users/users.go +++ /dev/null @@ -1,40 +0,0 @@ -package users - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -func createIfNecessary(monitor mntr.Monitor, user string, list []string, dbClient database.Client) operator.EnsureFunc { - existing := false - for _, listedUser := range list { - if listedUser == user { - existing = true - } - } - if !existing { - return func(k8sClient kubernetes.ClientInt) error { - return dbClient.AddUser(monitor, user, k8sClient) - } - } - - return nil -} - -func deleteIfNotRequired(monitor mntr.Monitor, listedUser string, list []string, dbClient database.Client) operator.EnsureFunc { - required := false - for _, user := range list { - if user == listedUser { - required = true - } - } - if !required { - return func(k8sClient kubernetes.ClientInt) error { - return dbClient.DeleteUser(monitor, listedUser, k8sClient) - } - } - - return nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/configuration/users/users_test.go b/operator/zitadel/kinds/iam/zitadel/configuration/users/users_test.go deleted file mode 100644 index badc762d8b..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/configuration/users/users_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package users - -import ( - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - databasemock "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestUsers_CreateIfNecessary(t *testing.T) { - users := []string{} - monitor := mntr.Monitor{} - user := "test" - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - dbClient.EXPECT().AddUser(monitor, user, k8sClient) - function := createIfNecessary(monitor, user, users, dbClient) - assert.NotNil(t, function) - err := function(k8sClient) - assert.NoError(t, err) - - users = []string{"test"} - function = createIfNecessary(monitor, user, users, dbClient) - assert.Nil(t, function) - - user2 := "test2" - dbClient.EXPECT().AddUser(monitor, user2, k8sClient) - function = createIfNecessary(monitor, user2, users, dbClient) - assert.NotNil(t, function) - err = function(k8sClient) - assert.NoError(t, err) -} - -func TestUsers_DeleteIfNotRequired(t *testing.T) { - users := []string{} - monitor := mntr.Monitor{} - user := "test" - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - dbClient.EXPECT().DeleteUser(monitor, user, k8sClient) - function := deleteIfNotRequired(monitor, user, users, dbClient) - assert.NotNil(t, function) - err := function(k8sClient) - assert.NoError(t, err) - - users = []string{"test"} - function = deleteIfNotRequired(monitor, user, users, dbClient) - assert.Nil(t, function) - - user2 := "test2" - dbClient.EXPECT().DeleteUser(monitor, user2, k8sClient) - function = deleteIfNotRequired(monitor, user2, users, dbClient) - assert.NotNil(t, function) - err = function(k8sClient) - assert.NoError(t, err) -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/adapt.go b/operator/zitadel/kinds/iam/zitadel/database/adapt.go deleted file mode 100644 index 711e9d8d80..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/adapt.go +++ /dev/null @@ -1,41 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" -) - -func AdaptFunc( - monitor mntr.Monitor, - dbClient Client, -) ( - operator.QueryFunc, - error, -) { - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - - dbHost, dbPort, err := dbClient.GetConnectionInfo(monitor, k8sClient) - if err != nil { - return nil, err - } - - users, err := dbClient.ListUsers(monitor, k8sClient) - if err != nil { - return nil, err - } - - curr := &Current{ - Host: dbHost, - Port: dbPort, - Users: users, - } - - SetDatabaseInQueried(queried, curr) - - return func(k8sClient kubernetes.ClientInt) error { - return nil - }, nil - }, nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/database/adapt_test.go deleted file mode 100644 index bb5cdd71fc..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/adapt_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package database - -import ( - "errors" - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - databasemock "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestDatabase_Adapt(t *testing.T) { - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - host := "host" - port := "port" - users := []string{"test"} - - monitor := mntr.Monitor{} - queried := map[string]interface{}{} - - dbClient.EXPECT().GetConnectionInfo(monitor, k8sClient).Return(host, port, nil) - dbClient.EXPECT().ListUsers(monitor, k8sClient).Return([]string{"test"}, nil) - - _, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - - query, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - - assert.NoError(t, ensure(k8sClient)) - - current, err := GetDatabaseInQueried(queried) - assert.NoError(t, err) - assert.Equal(t, host, current.Host) - assert.Equal(t, port, current.Port) - assert.Equal(t, users, current.Users) -} - -func TestDatabase_Adapt2(t *testing.T) { - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - host := "host2" - port := "port2" - users := []string{"test2"} - - monitor := mntr.Monitor{} - queried := map[string]interface{}{} - - dbClient.EXPECT().GetConnectionInfo(monitor, k8sClient).Return(host, port, nil) - dbClient.EXPECT().ListUsers(monitor, k8sClient).Return(users, nil) - - _, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - - query, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - - assert.NoError(t, ensure(k8sClient)) - - current, err := GetDatabaseInQueried(queried) - assert.NoError(t, err) - assert.Equal(t, host, current.Host) - assert.Equal(t, port, current.Port) - assert.Equal(t, users, current.Users) -} - -func TestDatabase_AdaptFailConnection(t *testing.T) { - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - monitor := mntr.Monitor{} - queried := map[string]interface{}{} - - dbClient.EXPECT().GetConnectionInfo(monitor, k8sClient).MinTimes(1).MaxTimes(1).Return("", "", errors.New("fail")) - dbClient.EXPECT().ListUsers(monitor, k8sClient).MinTimes(1).MaxTimes(1).Return([]string{"test"}, nil) - - _, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - - query, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - ensure, err := query(k8sClient, queried) - assert.Error(t, err) - assert.Nil(t, ensure) - - current, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - assert.Nil(t, current) -} - -func TestDatabase_AdaptFailUsers(t *testing.T) { - dbClient := databasemock.NewMockClient(gomock.NewController(t)) - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - host := "host" - port := "port" - - monitor := mntr.Monitor{} - queried := map[string]interface{}{} - - dbClient.EXPECT().GetConnectionInfo(monitor, k8sClient).Return(host, port, nil) - dbClient.EXPECT().ListUsers(monitor, k8sClient).Return(nil, errors.New("fail")) - - _, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - - query, err := AdaptFunc(monitor, dbClient) - assert.NoError(t, err) - ensure, err := query(k8sClient, queried) - assert.Error(t, err) - assert.Nil(t, ensure) - - current, err := GetDatabaseInQueried(queried) - assert.Error(t, err) - assert.Nil(t, current) -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/client.go b/operator/zitadel/kinds/iam/zitadel/database/client.go deleted file mode 100644 index 3b5cad3cef..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/client.go +++ /dev/null @@ -1,74 +0,0 @@ -package database - -import ( - "context" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/pkg/databases" -) - -var _ Client = (*GitOpsClient)(nil) -var _ Client = (*CrdClient)(nil) - -type Client interface { - GetConnectionInfo(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) (string, string, error) - DeleteUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error - AddUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error - ListUsers(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) ([]string, error) -} - -type GitOpsClient struct { - Monitor mntr.Monitor - gitClient *git.Client -} - -func NewGitOpsClient(monitor mntr.Monitor, repoURL, repoKey string) (*GitOpsClient, error) { - gitClient, err := newGit(monitor, repoURL, repoKey) - if err != nil { - return nil, err - } - - return &GitOpsClient{ - Monitor: monitor, - gitClient: gitClient, - }, nil -} - -func newGit(monitor mntr.Monitor, repoURL string, repoKey string) (*git.Client, error) { - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(repoURL, []byte(repoKey)); err != nil { - return nil, err - } - - if err := gitClient.Clone(); err != nil { - return nil, err - } - return gitClient, nil -} - -func (c *GitOpsClient) GetConnectionInfo(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) (string, string, error) { - return databases.GitOpsGetConnectionInfo( - monitor, - k8sClient, - c.gitClient, - ) -} - -type CrdClient struct { - Monitor mntr.Monitor -} - -func NewCrdClient(monitor mntr.Monitor) *CrdClient { - return &CrdClient{ - Monitor: monitor, - } -} - -func (c *CrdClient) GetConnectionInfo(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) (string, string, error) { - return databases.CrdGetConnectionInfo( - monitor, - k8sClient, - ) -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/database.go b/operator/zitadel/kinds/iam/zitadel/database/database.go deleted file mode 100644 index 81a00cb044..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/database.go +++ /dev/null @@ -1,24 +0,0 @@ -package database - -import ( - "errors" -) - -type Current struct { - Host string - Port string - Users []string -} - -func SetDatabaseInQueried(queried map[string]interface{}, current *Current) { - queried["database"] = current -} - -func GetDatabaseInQueried(queried map[string]interface{}) (*Current, error) { - curr, ok := queried["database"].(*Current) - if !ok { - return nil, errors.New("database current not in supported format") - } - - return curr, nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/generate.go b/operator/zitadel/kinds/iam/zitadel/database/generate.go deleted file mode 100644 index cf72c46b63..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package database - -//go:generate mockgen -source client.go -package databasemock -destination mock/client.mock.go github.com/caos/zitadel/operator/kinds/iam/zitadel/database ClientInt diff --git a/operator/zitadel/kinds/iam/zitadel/database/mock/client.mock.go b/operator/zitadel/kinds/iam/zitadel/database/mock/client.mock.go deleted file mode 100644 index 9bf593bec7..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/mock/client.mock.go +++ /dev/null @@ -1,94 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: client.go - -// Package databasemock is a generated GoMock package. -package databasemock - -import ( - mntr "github.com/caos/orbos/mntr" - kubernetes "github.com/caos/orbos/pkg/kubernetes" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockClient is a mock of Client interface -type MockClient struct { - ctrl *gomock.Controller - recorder *MockClientMockRecorder -} - -// MockClientMockRecorder is the mock recorder for MockClient -type MockClientMockRecorder struct { - mock *MockClient -} - -// NewMockClient creates a new mock instance -func NewMockClient(ctrl *gomock.Controller) *MockClient { - mock := &MockClient{ctrl: ctrl} - mock.recorder = &MockClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockClient) EXPECT() *MockClientMockRecorder { - return m.recorder -} - -// GetConnectionInfo mocks base method -func (m *MockClient) GetConnectionInfo(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) (string, string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetConnectionInfo", monitor, k8sClient) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(string) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetConnectionInfo indicates an expected call of GetConnectionInfo -func (mr *MockClientMockRecorder) GetConnectionInfo(monitor, k8sClient interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConnectionInfo", reflect.TypeOf((*MockClient)(nil).GetConnectionInfo), monitor, k8sClient) -} - -// DeleteUser mocks base method -func (m *MockClient) DeleteUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteUser", monitor, user, k8sClient) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteUser indicates an expected call of DeleteUser -func (mr *MockClientMockRecorder) DeleteUser(monitor, user, k8sClient interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUser", reflect.TypeOf((*MockClient)(nil).DeleteUser), monitor, user, k8sClient) -} - -// AddUser mocks base method -func (m *MockClient) AddUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddUser", monitor, user, k8sClient) - ret0, _ := ret[0].(error) - return ret0 -} - -// AddUser indicates an expected call of AddUser -func (mr *MockClientMockRecorder) AddUser(monitor, user, k8sClient interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUser", reflect.TypeOf((*MockClient)(nil).AddUser), monitor, user, k8sClient) -} - -// ListUsers mocks base method -func (m *MockClient) ListUsers(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListUsers", monitor, k8sClient) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ListUsers indicates an expected call of ListUsers -func (mr *MockClientMockRecorder) ListUsers(monitor, k8sClient interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUsers", reflect.TypeOf((*MockClient)(nil).ListUsers), monitor, k8sClient) -} diff --git a/operator/zitadel/kinds/iam/zitadel/database/user.go b/operator/zitadel/kinds/iam/zitadel/database/user.go deleted file mode 100644 index ab1118e603..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/database/user.go +++ /dev/null @@ -1,56 +0,0 @@ -package database - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/pkg/databases" -) - -func (c *GitOpsClient) DeleteUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - return databases.GitOpsDeleteUser( - monitor, - user, - k8sClient, - c.gitClient, - ) -} - -func (c *GitOpsClient) AddUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - return databases.GitOpsAddUser( - monitor, - user, - k8sClient, - c.gitClient, - ) -} - -func (c *GitOpsClient) ListUsers(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) ([]string, error) { - return databases.GitOpsListUsers( - monitor, - k8sClient, - c.gitClient, - ) -} - -func (c *CrdClient) DeleteUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - return databases.CrdDeleteUser( - monitor, - user, - k8sClient, - ) -} - -func (c *CrdClient) AddUser(monitor mntr.Monitor, user string, k8sClient kubernetes.ClientInt) error { - return databases.CrdAddUser( - monitor, - user, - k8sClient, - ) -} - -func (c *CrdClient) ListUsers(monitor mntr.Monitor, k8sClient kubernetes.ClientInt) ([]string, error) { - return databases.CrdListUsers( - monitor, - k8sClient, - ) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/adapt.go b/operator/zitadel/kinds/iam/zitadel/deployment/adapt.go deleted file mode 100644 index ceca1c9ac0..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/adapt.go +++ /dev/null @@ -1,218 +0,0 @@ -package deployment - -import ( - "time" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/caos/orbos/pkg/kubernetes/resources/deployment" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/helpers" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - rootSecret = "client-root" - dbSecrets = "db-secrets" - containerName = "zitadel" - RunAsUser = int64(1000) - //zitadelImage can be found in github.com/caos/zitadel repo - timeout = 60 * time.Second -) - -func AdaptFunc( - monitor mntr.Monitor, - nameLabels *labels.Name, - podSelector *labels.Selector, - force bool, - version *string, - namespace string, - replicaCount int, - affinity *k8s.Affinity, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordsName string, - nodeSelector map[string]string, - tolerations []corev1.Toleration, - resources *k8s.Resources, - migrationDone operator.EnsureFunc, - configurationDone operator.EnsureFunc, - setupDone operator.EnsureFunc, - customImageRegistry string, -) ( - func( - necessaryUsers map[string]string, - getConfigurationHashes func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error), - ) operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("type", "deployment") - - destroy, err := deployment.AdaptFuncToDestroy(namespace, nameLabels.Name()) - if err != nil { - return nil, nil, err - } - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroy), - } - - return func( - necessaryUsers map[string]string, - getConfigurationHashes func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error), - ) operator.QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - users := make([]string, 0) - for user := range necessaryUsers { - users = append(users, user) - } - - deploymentDef := deploymentDef( - nameLabels, - namespace, - replicaCount, - podSelector, - nodeSelector, - tolerations, - affinity, - users, - version, - resources, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - customImageRegistry, - ) - - hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers) - if err != nil { - return nil, err - } - if hashes != nil && len(hashes) != 0 { - for k, v := range hashes { - deploymentDef.Annotations[k] = v - deploymentDef.Spec.Template.Annotations[k] = v - } - } - - query, err := deployment.AdaptFuncToEnsure(deploymentDef, force) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.EnsureFuncToQueryFunc(migrationDone), - operator.EnsureFuncToQueryFunc(configurationDone), - operator.EnsureFuncToQueryFunc(setupDone), - operator.ResourceQueryToZitadelQuery(query), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - } - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil - -} - -func deploymentDef( - nameLabels *labels.Name, - namespace string, - replicaCount int, - podSelector *labels.Selector, - nodeSelector map[string]string, - tolerations []corev1.Toleration, - affinity *k8s.Affinity, - users []string, - version *string, - resources *k8s.Resources, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordsName string, - customImageRegistry string, -) *appsv1.Deployment { - deploymentDef := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(nameLabels), - Annotations: map[string]string{}, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: helpers.PointerInt32(int32(replicaCount)), - Selector: &metav1.LabelSelector{ - MatchLabels: labels.MustK8sMap(podSelector), - }, - Strategy: appsv1.DeploymentStrategy{ - Type: appsv1.RollingUpdateDeploymentStrategyType, - RollingUpdate: &appsv1.RollingUpdateDeployment{ - MaxUnavailable: helpers.IntToIntStr(1), - MaxSurge: helpers.IntToIntStr(1), - }, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - Annotations: map[string]string{}, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeSelector, - Tolerations: tolerations, - Affinity: affinity.K8s(), - InitContainers: []corev1.Container{ - GetInitContainer( - rootSecret, - dbSecrets, - users, - RunAsUser, - customImageRegistry, - ), - }, - Containers: []corev1.Container{ - GetContainer( - containerName, - *version, - RunAsUser, - true, - GetResourcesFromDefault(resources), - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - users, - dbSecrets, - "start", - customImageRegistry, - ), - }, - Volumes: GetVolumes( - secretName, - secretPasswordsName, - consoleCMName, - users, - ), - }, - }, - }, - } - return deploymentDef -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/adapt_test.go deleted file mode 100644 index 1970fbb0a6..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/adapt_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package deployment - -import ( - "testing" - - "github.com/caos/orbos/pkg/labels/mocklabels" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/k8s" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/zitadel/operator/helpers" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestDeployment_Adapt(t *testing.T) { - monitor := mntr.Monitor{} - imageVersion := "test" - namespace := "test" - - replicaCount := 1 - nodeSelector := map[string]string{"test": "test"} - secretVarsName := "testVars" - secretPasswordsName := "testPasswords" - secretPath := "testSecretPath" - certPath := "testCert" - secretName := "testSecret" - consoleCMName := "testConsoleCM" - cmName := "testCM" - customImageRegistry := "" - - usersMap := map[string]string{"test": "test"} - users := []string{} - for _, user := range usersMap { - users = append(users, user) - } - annotations := map[string]string{"testHash": "test"} - - k8sClient := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - resources := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("512Mi"), - }, - } - - deploymentDef := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: mocklabels.NameVal, - Namespace: namespace, - Labels: mocklabels.NameMap, - Annotations: annotations, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: helpers.PointerInt32(int32(replicaCount)), - Selector: &metav1.LabelSelector{ - MatchLabels: mocklabels.ClosedNameSelectorMap, - }, - Strategy: appsv1.DeploymentStrategy{ - Type: appsv1.RollingUpdateDeploymentStrategyType, - RollingUpdate: &appsv1.RollingUpdateDeployment{ - MaxUnavailable: helpers.IntToIntStr(1), - MaxSurge: helpers.IntToIntStr(1), - }, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: mocklabels.SelectableMap, - Annotations: annotations, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeSelector, - Tolerations: nil, - Affinity: nil, - InitContainers: []corev1.Container{ - GetInitContainer( - rootSecret, - dbSecrets, - users, - RunAsUser, - customImageRegistry, - ), - }, - Containers: []corev1.Container{ - GetContainer( - containerName, - imageVersion, - RunAsUser, - true, - resources, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - users, - dbSecrets, - "start", - customImageRegistry, - ), - }, - Volumes: GetVolumes( - secretName, - secretPasswordsName, - consoleCMName, - users, - ), - }, - }, - }, - } - k8sClient.EXPECT().ApplyDeployment(deploymentDef, false).Times(1) - - getConfigurationHashes := func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error) { - return map[string]string{"testHash": "test"}, nil - } - migrationDone := func(k8sClient kubernetes.ClientInt) error { - return nil - } - configurationDone := func(k8sClient kubernetes.ClientInt) error { - return nil - } - setupDone := func(k8sClient kubernetes.ClientInt) error { - return nil - } - - getQuery, _, err := AdaptFunc( - monitor, - mocklabels.Name, - mocklabels.ClosedNameSelector, - false, - &imageVersion, - namespace, - replicaCount, - nil, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - nodeSelector, - nil, - resources, - migrationDone, - configurationDone, - setupDone, - customImageRegistry, - ) - assert.NoError(t, err) - queried := map[string]interface{}{} - query := getQuery(usersMap, getConfigurationHashes) - ensure, err := query(k8sClient, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(k8sClient)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/container.go b/operator/zitadel/kinds/iam/zitadel/deployment/container.go deleted file mode 100644 index ed08c56929..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/container.go +++ /dev/null @@ -1,173 +0,0 @@ -package deployment - -import ( - "sort" - "strings" - - "github.com/caos/zitadel/operator/common" - - "github.com/caos/orbos/pkg/kubernetes/k8s" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func GetContainer( - containerName string, - version string, - runAsUser int64, - runAsNonRoot bool, - resources *k8s.Resources, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordsName string, - users []string, - dbSecrets string, - command string, - customImageRegistry string, -) corev1.Container { - - envVars := []corev1.EnvVar{ - {Name: "POD_IP", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "status.podIP", - }, - }}, - {Name: "CHAT_URL", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_GOOGLE_CHAT_URL", - }, - }}, - {Name: "TWILIO_TOKEN", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_TWILIO_AUTH_TOKEN", - }, - }}, - {Name: "TWILIO_SERVICE_SID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_TWILIO_SID", - }, - }}, - {Name: "SMTP_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_EMAILAPPKEY", - }, - }}, - {Name: "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID", - }, - }}, - {Name: "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY", - }, - }}, - {Name: "HTTP_PROXY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "HTTP_PROXY", - }, - }}, - {Name: "HTTPS_PROXY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "HTTPS_PROXY", - }, - }}, - {Name: "SENTRY_DSN", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "SENTRY_DSN", - }, - }}, - } - - sort.Strings(users) - for _, user := range users { - envVars = append(envVars, corev1.EnvVar{ - Name: "CR_" + strings.ToUpper(user) + "_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretPasswordsName}, - Key: user, - }, - }, - }) - } - - volMounts := []corev1.VolumeMount{ - {Name: secretName, MountPath: secretPath}, - {Name: consoleCMName, MountPath: "/console/environment.json", SubPath: "environment.json"}, - {Name: dbSecrets, MountPath: certPath}, - } - - return corev1.Container{ - Resources: corev1.ResourceRequirements(*resources), - //Command: []string{"/bin/sh", "-c"}, - //Args: []string{"tail -f /dev/null;"}, - Args: []string{command}, - SecurityContext: &corev1.SecurityContext{ - RunAsUser: &runAsUser, - RunAsNonRoot: &runAsNonRoot, - }, - Name: containerName, - Image: common.ZITADELImage.Reference(customImageRegistry, version), - ImagePullPolicy: corev1.PullIfNotPresent, - Ports: []corev1.ContainerPort{ - {Name: "grpc", ContainerPort: 50001}, - {Name: "http", ContainerPort: 50002}, - {Name: "ui", ContainerPort: 50003}, - }, - Env: envVars, - EnvFrom: []corev1.EnvFromSource{ - {ConfigMapRef: &corev1.ConfigMapEnvSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: cmName}, - }}}, - VolumeMounts: volMounts, - /*LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/healthz", - Port: intstr.Parse("http"), - Scheme: "HTTP", - }, - }, - PeriodSeconds: 5, - FailureThreshold: 2, - InitialDelaySeconds: 60, - },*/ - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/ready", - Port: intstr.Parse("http"), - Scheme: "HTTP", - }, - }, - PeriodSeconds: 5, - FailureThreshold: 2, - }, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/container_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/container_test.go deleted file mode 100644 index 90370f2f08..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/container_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package deployment - -import ( - "fmt" - "testing" - - "github.com/caos/zitadel/operator/common" - - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/util/intstr" - - "github.com/caos/zitadel/operator/helpers" -) - -func TestDeployment_GetContainer(t *testing.T) { - secretVarsName := "testVars" - version := "test" - secretPasswordsName := "testPasswords" - secretPath := "testSecretPath" - certPath := "testCert" - secretName := "testSecret" - consoleCMName := "testConsoleCM" - cmName := "testCM" - users := []string{"test"} - - resources := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("512Mi"), - }, - } - - envVars := []corev1.EnvVar{ - {Name: "POD_IP", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "status.podIP", - }, - }}, - {Name: "CHAT_URL", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_GOOGLE_CHAT_URL", - }, - }}, - {Name: "TWILIO_TOKEN", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_TWILIO_AUTH_TOKEN", - }, - }}, - {Name: "TWILIO_SERVICE_SID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_TWILIO_SID", - }, - }}, - {Name: "SMTP_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_EMAILAPPKEY", - }, - }}, - {Name: "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID", - }, - }}, - {Name: "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY", - }, - }}, - {Name: "HTTP_PROXY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "HTTP_PROXY", - }, - }}, - {Name: "HTTPS_PROXY", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "HTTPS_PROXY", - }, - }}, - {Name: "SENTRY_DSN", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretVarsName}, - Key: "SENTRY_DSN", - }, - }, - }, - { - Name: "CR_TEST_PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secretPasswordsName}, - Key: "test", - }, - }, - }, - } - - volMounts := []corev1.VolumeMount{ - {Name: secretName, MountPath: secretPath}, - {Name: consoleCMName, MountPath: "/console/environment.json", SubPath: "environment.json"}, - {Name: dbSecrets, MountPath: certPath}, - } - - equals := corev1.Container{ - Resources: corev1.ResourceRequirements(*resources), - //Command: []string{"/bin/sh", "-c"}, - //Args: []string{"tail -f /dev/null;"}, - Args: []string{"start"}, - SecurityContext: &corev1.SecurityContext{ - RunAsUser: helpers.PointerInt64(RunAsUser), - RunAsNonRoot: helpers.PointerBool(true), - }, - Name: containerName, - Image: fmt.Sprintf("ghcr.io/%s:%s", common.ZITADELImage, version), - ImagePullPolicy: corev1.PullIfNotPresent, - Ports: []corev1.ContainerPort{ - {Name: "grpc", ContainerPort: 50001}, - {Name: "http", ContainerPort: 50002}, - {Name: "ui", ContainerPort: 50003}, - }, - Env: envVars, - EnvFrom: []corev1.EnvFromSource{ - {ConfigMapRef: &corev1.ConfigMapEnvSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: cmName}, - }}}, - VolumeMounts: volMounts, - /*LivenessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/healthz", - Port: intstr.Parse("http"), - Scheme: "HTTP", - }, - }, - PeriodSeconds: 5, - FailureThreshold: 2, - InitialDelaySeconds: 60, - },*/ - ReadinessProbe: &corev1.Probe{ - Handler: corev1.Handler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: "/ready", - Port: intstr.Parse("http"), - Scheme: "HTTP", - }, - }, - PeriodSeconds: 5, - FailureThreshold: 2, - }, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - } - - container := GetContainer( - containerName, - version, - RunAsUser, - true, - resources, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - users, - dbSecrets, - "start", - "", - ) - - assert.Equal(t, equals, container) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer.go b/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer.go deleted file mode 100644 index 811f0f88d9..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer.go +++ /dev/null @@ -1,62 +0,0 @@ -package deployment - -import ( - "sort" - "strconv" - "strings" - - "github.com/caos/zitadel/operator/common" - - corev1 "k8s.io/api/core/v1" -) - -const ( - certMountPath = "/dbsecrets" - certTempMountPath = "/tmp/dbsecrets" -) - -func GetInitContainer( - rootSecret string, - dbSecrets string, - users []string, - runAsUser int64, - customImageRegistry string, -) corev1.Container { - - initVolumeMounts := []corev1.VolumeMount{ - {Name: rootSecret, MountPath: certMountPath + "/client_root"}, - {Name: dbSecrets, MountPath: certTempMountPath}, - } - - copySecrets := append([]string{}, "cp "+certMountPath+"/client_root/ca.crt "+certTempMountPath+"/ca.crt") - - sort.Strings(users) - for _, user := range users { - userReplaced := strings.ReplaceAll(user, "_", "-") - internalName := "client-" + userReplaced - initVolumeMounts = append(initVolumeMounts, corev1.VolumeMount{ - Name: internalName, - //ReadOnly: true, - MountPath: certMountPath + "/client_" + user, - }) - copySecrets = append(copySecrets, "cp "+certMountPath+"/client_"+user+"/client."+user+".crt "+certTempMountPath+"/client."+user+".crt") - copySecrets = append(copySecrets, "cp "+certMountPath+"/client_"+user+"/client."+user+".key "+certTempMountPath+"/client."+user+".key") - } - - initCommands := append( - copySecrets, - "chown -R "+strconv.FormatInt(runAsUser, 10)+":"+strconv.FormatInt(runAsUser, 10)+" "+certTempMountPath+"", - "chmod 0600 "+certTempMountPath+"/*", - ) - - return corev1.Container{ - Name: "fix-permissions", - Image: common.AlpineImage.Reference(customImageRegistry), - Command: []string{"/bin/sh", "-c"}, - Args: []string{strings.Join(initCommands, " && ")}, - VolumeMounts: initVolumeMounts, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - ImagePullPolicy: corev1.PullIfNotPresent, - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer_test.go deleted file mode 100644 index 24144fcbbe..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/initcontainer_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package deployment - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" -) - -func TestDeployment_GetInitContainer(t *testing.T) { - users := []string{"test"} - - initCommands := []string{ - "cp /dbsecrets/client_root/ca.crt /tmp/dbsecrets/ca.crt", - "cp /dbsecrets/client_test/client.test.crt /tmp/dbsecrets/client.test.crt", - "cp /dbsecrets/client_test/client.test.key /tmp/dbsecrets/client.test.key", - "chown -R 1000:1000 /tmp/dbsecrets", - "chmod 0600 /tmp/dbsecrets/*", - } - - initVolumeMounts := []corev1.VolumeMount{ - {Name: rootSecret, MountPath: certMountPath + "/client_root"}, - {Name: dbSecrets, MountPath: certTempMountPath}, - {Name: "client-test", MountPath: certMountPath + "/client_test"}, - } - - equals := corev1.Container{ - Name: "fix-permissions", - Image: "alpine:3.11", - Command: []string{"/bin/sh", "-c"}, - Args: []string{strings.Join(initCommands, " && ")}, - VolumeMounts: initVolumeMounts, - ImagePullPolicy: corev1.PullIfNotPresent, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - } - - init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "") - - assert.Equal(t, equals, init) -} - -func TestDeployment_GetInitContainer1(t *testing.T) { - users := []string{"test1"} - - initCommands := []string{ - "cp /dbsecrets/client_root/ca.crt /tmp/dbsecrets/ca.crt", - "cp /dbsecrets/client_test1/client.test1.crt /tmp/dbsecrets/client.test1.crt", - "cp /dbsecrets/client_test1/client.test1.key /tmp/dbsecrets/client.test1.key", - "chown -R 1000:1000 /tmp/dbsecrets", - "chmod 0600 /tmp/dbsecrets/*", - } - - initVolumeMounts := []corev1.VolumeMount{ - {Name: rootSecret, MountPath: certMountPath + "/client_root"}, - {Name: dbSecrets, MountPath: certTempMountPath}, - {Name: "client-test1", MountPath: certMountPath + "/client_test1"}, - } - - equals := corev1.Container{ - Name: "fix-permissions", - Image: "alpine:3.11", - Command: []string{"/bin/sh", "-c"}, - Args: []string{strings.Join(initCommands, " && ")}, - VolumeMounts: initVolumeMounts, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - ImagePullPolicy: corev1.PullIfNotPresent, - } - - init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "") - - assert.Equal(t, equals, init) -} - -func TestDeployment_GetInitContainer2(t *testing.T) { - users := []string{"test1", "test2"} - - initCommands := []string{ - "cp /dbsecrets/client_root/ca.crt /tmp/dbsecrets/ca.crt", - "cp /dbsecrets/client_test1/client.test1.crt /tmp/dbsecrets/client.test1.crt", - "cp /dbsecrets/client_test1/client.test1.key /tmp/dbsecrets/client.test1.key", - "cp /dbsecrets/client_test2/client.test2.crt /tmp/dbsecrets/client.test2.crt", - "cp /dbsecrets/client_test2/client.test2.key /tmp/dbsecrets/client.test2.key", - "chown -R 1000:1000 /tmp/dbsecrets", - "chmod 0600 /tmp/dbsecrets/*", - } - - initVolumeMounts := []corev1.VolumeMount{ - {Name: rootSecret, MountPath: certMountPath + "/client_root"}, - {Name: dbSecrets, MountPath: certTempMountPath}, - {Name: "client-test1", MountPath: certMountPath + "/client_test1"}, - {Name: "client-test2", MountPath: certMountPath + "/client_test2"}, - } - - equals := corev1.Container{ - Name: "fix-permissions", - Image: "alpine:3.11", - Command: []string{"/bin/sh", "-c"}, - Args: []string{strings.Join(initCommands, " && ")}, - VolumeMounts: initVolumeMounts, - ImagePullPolicy: corev1.PullIfNotPresent, - TerminationMessagePolicy: "File", - TerminationMessagePath: "/dev/termination-log", - } - - init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "") - - assert.Equal(t, equals, init) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/ready.go b/operator/zitadel/kinds/iam/zitadel/deployment/ready.go deleted file mode 100644 index 26b80e2e4c..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/ready.go +++ /dev/null @@ -1,23 +0,0 @@ -package deployment - -import ( - "fmt" - "time" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/zitadel/operator" -) - -func GetReadyFunc(monitor mntr.Monitor, namespace string, name *labels.Name) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for deployment to be ready") - if err := k8sClient.WaitUntilDeploymentReady(namespace, name.Name(), true, true, 60*time.Second); err != nil { - return fmt.Errorf("error while waiting for deployment to be ready: %w", err) - } - monitor.Info("deployment is ready") - return nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/ready_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/ready_test.go deleted file mode 100644 index 0f353d4eef..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/ready_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package deployment - -import ( - "errors" - "testing" - - "github.com/caos/orbos/pkg/labels/mocklabels" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestDeployment_Ready1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - - client.EXPECT().WaitUntilDeploymentReady(namespace, mocklabels.NameVal, true, true, timeout).Times(1).Return(nil) - readyFunc := GetReadyFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, readyFunc) - assert.NoError(t, readyFunc(client)) -} - -func TestDeployment_Ready2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - - client.EXPECT().WaitUntilDeploymentReady(namespace, mocklabels.NameVal, true, true, timeout).Times(1).Return(nil) - readyFunc := GetReadyFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, readyFunc) - assert.NoError(t, readyFunc(client)) -} - -func TestDeployment_ReadyFailure1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - - client.EXPECT().WaitUntilDeploymentReady(namespace, mocklabels.NameVal, true, true, timeout).Times(1).Return(errors.New("fail")) - readyFunc := GetReadyFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} - -func TestDeployment_ReadyFailure2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - - client.EXPECT().WaitUntilDeploymentReady(namespace, mocklabels.NameVal, true, true, timeout).Times(1).Return(errors.New("fail")) - readyFunc := GetReadyFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, readyFunc) - assert.Error(t, readyFunc(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/resources.go b/operator/zitadel/kinds/iam/zitadel/deployment/resources.go deleted file mode 100644 index 73f3e8375b..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/resources.go +++ /dev/null @@ -1,24 +0,0 @@ -package deployment - -import ( - "github.com/caos/orbos/pkg/kubernetes/k8s" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" -) - -func GetResourcesFromDefault(resources *k8s.Resources) *k8s.Resources { - ret := resources - if ret == nil { - ret = &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("512Mi"), - }, - } - } - return ret -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/resources_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/resources_test.go deleted file mode 100644 index 570a28e6cf..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/resources_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package deployment - -import ( - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - "testing" -) - -func TestDeployment_ResourcesDefault1(t *testing.T) { - test := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("1Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - } - - resources := GetResourcesFromDefault(test) - assert.Equal(t, resources, test) -} - -func TestDeployment_ResourcesDefault2(t *testing.T) { - test := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("512Mi"), - }, - } - - resources := GetResourcesFromDefault(nil) - assert.Equal(t, resources, test) -} - -func TestDeployment_ResourcesDefault3(t *testing.T) { - test := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("1Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("200m"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - } - - resources := GetResourcesFromDefault(test) - assert.Equal(t, resources, test) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/scale.go b/operator/zitadel/kinds/iam/zitadel/deployment/scale.go deleted file mode 100644 index a44c63d5a4..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/scale.go +++ /dev/null @@ -1,17 +0,0 @@ -package deployment - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" -) - -func GetScaleFunc(monitor mntr.Monitor, namespace string, name *labels.Name) func(replicaCount int) operator.EnsureFunc { - return func(replicaCount int) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("Scaling deployment") - return k8sClient.ScaleDeployment(namespace, name.Name(), replicaCount) - } - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/scale_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/scale_test.go deleted file mode 100644 index cad39af848..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/scale_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package deployment - -import ( - "errors" - "testing" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" -) - -func TestDeployment_Scale1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - replicaCount := 1 - - client.EXPECT().ScaleDeployment(namespace, mocklabels.NameVal, replicaCount).Times(1).Return(nil) - scaleFunc := GetScaleFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, scaleFunc) - ensure := scaleFunc(replicaCount) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestDeployment_Scale2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - replicaCount := 0 - - client.EXPECT().ScaleDeployment(namespace, mocklabels.NameVal, replicaCount).Times(1).Return(nil) - scaleFunc := GetScaleFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, scaleFunc) - ensure := scaleFunc(replicaCount) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestDeployment_Scale3(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - replicaCount := 3 - - client.EXPECT().ScaleDeployment(namespace, mocklabels.NameVal, replicaCount).Times(1).Return(nil) - scaleFunc := GetScaleFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, scaleFunc) - ensure := scaleFunc(replicaCount) - assert.NotNil(t, ensure) - assert.NoError(t, ensure(client)) -} - -func TestDeployment_ScaleFailure1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - replicaCount := 0 - - client.EXPECT().ScaleDeployment(namespace, mocklabels.NameVal, replicaCount).Times(1).Return(errors.New("fail")) - scaleFunc := GetScaleFunc(monitor, namespace, mocklabels.Name) - assert.NotNil(t, scaleFunc) - ensure := scaleFunc(replicaCount) - assert.NotNil(t, ensure) - assert.Error(t, ensure(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/volumes.go b/operator/zitadel/kinds/iam/zitadel/deployment/volumes.go deleted file mode 100644 index 716bac43de..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/volumes.go +++ /dev/null @@ -1,78 +0,0 @@ -package deployment - -import ( - "github.com/caos/zitadel/operator/helpers" - corev1 "k8s.io/api/core/v1" - "sort" - "strings" -) - -func GetVolumes( - secretName string, - secretPasswordsName string, - consoleCMName string, - users []string, -) []corev1.Volume { - volumes := []corev1.Volume{{ - Name: secretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - DefaultMode: helpers.PointerInt32(420), - }, - }, - }, { - Name: rootSecret, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.root", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }, { - Name: secretPasswordsName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretPasswordsName, - DefaultMode: helpers.PointerInt32(384), - }, - }, - }, { - Name: consoleCMName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: consoleCMName}, - DefaultMode: helpers.PointerInt32(420), - }, - }, - }, { - Name: dbSecrets, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }} - - return append(volumes, userVolumes(users)...) -} - -func userVolumes( - users []string, -) []corev1.Volume { - volumes := make([]corev1.Volume, 0) - - sort.Strings(users) - for _, user := range users { - userReplaced := strings.ReplaceAll(user, "_", "-") - internalName := "client-" + userReplaced - volumes = append(volumes, corev1.Volume{ - Name: internalName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client." + userReplaced, - DefaultMode: helpers.PointerInt32(384), - }, - }, - }) - } - return volumes -} diff --git a/operator/zitadel/kinds/iam/zitadel/deployment/volumes_test.go b/operator/zitadel/kinds/iam/zitadel/deployment/volumes_test.go deleted file mode 100644 index f636e38140..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/deployment/volumes_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package deployment - -import ( - "github.com/caos/zitadel/operator/helpers" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "testing" -) - -func TestDeployment_Volumes(t *testing.T) { - secretName := "testSecret" - secretPasswordsName := "testPasswords" - consoleCMName := "testCM" - users := []string{"test"} - - equals := []corev1.Volume{{ - Name: secretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, - DefaultMode: helpers.PointerInt32(420), - }, - }, - }, { - Name: rootSecret, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.root", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }, { - Name: secretPasswordsName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretPasswordsName, - DefaultMode: helpers.PointerInt32(384), - }, - }, - }, { - Name: consoleCMName, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: consoleCMName}, - DefaultMode: helpers.PointerInt32(420), - }, - }, - }, { - Name: dbSecrets, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, {Name: "client-test", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.test", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }} - - assert.ElementsMatch(t, equals, GetVolumes(secretName, secretPasswordsName, consoleCMName, users)) - -} - -func TestDeployment_UserVolumes(t *testing.T) { - users := []string{"test"} - equals := []corev1.Volume{ - {Name: "client-test", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.test", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }} - - assert.ElementsMatch(t, equals, userVolumes(users)) - - users = []string{"te_st"} - equals = []corev1.Volume{ - {Name: "client-te-st", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.te-st", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }} - - assert.ElementsMatch(t, equals, userVolumes(users)) - - users = []string{"test", "te-st"} - equals = []corev1.Volume{ - {Name: "client-test", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.test", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }, {Name: "client-te-st", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.te-st", - DefaultMode: helpers.PointerInt32(384), - }, - }, - }} - - assert.ElementsMatch(t, equals, userVolumes(users)) - -} diff --git a/operator/zitadel/kinds/iam/zitadel/desired.go b/operator/zitadel/kinds/iam/zitadel/desired.go deleted file mode 100644 index 67af0f5851..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/desired.go +++ /dev/null @@ -1,51 +0,0 @@ -package zitadel - -import ( - "fmt" - - corev1 "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec *Spec -} - -type Spec struct { - Verbose bool - Force bool - ReplicaCount int `yaml:"replicaCount,omitempty"` - Configuration *configuration.Configuration `yaml:"configuration"` - NodeSelector map[string]string `yaml:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `yaml:"tolerations,omitempty"` - Affinity *k8s.Affinity `yaml:"affinity,omitempty"` - Resources *k8s.Resources `yaml:"resources,omitempty"` -} - -func (s *Spec) validate() (err error) { - defer func() { - if err != nil { - err = mntr.ToUserError(fmt.Errorf("validating spec failed: %w", err)) - } - }() - - return s.Configuration.Validate() -} - -func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{ - Common: desiredTree.Common, - Spec: &Spec{}, - } - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err)) - } - return desiredKind, nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/labels.go b/operator/zitadel/kinds/iam/zitadel/labels.go deleted file mode 100644 index e3566e2824..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/labels.go +++ /dev/null @@ -1,11 +0,0 @@ -package zitadel - -/* -func getLabels() map[string]string { - return map[string]string{ - "app.kubernetes.io/managed-by": "zitadel.caos.ch", - "app.kubernetes.io/part-of": "zitadel", - "app.kubernetes.io/component": "iam", - } -} -*/ diff --git a/operator/zitadel/kinds/iam/zitadel/migration/adapt.go b/operator/zitadel/kinds/iam/zitadel/migration/adapt.go deleted file mode 100644 index d1849e26e3..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/adapt.go +++ /dev/null @@ -1,246 +0,0 @@ -package migration - -import ( - "crypto/sha512" - "encoding/base64" - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "sort" - - "github.com/rakyll/statik/fs" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/configmap" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/helpers" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - _ "github.com/caos/zitadel/statik" -) - -const ( - migrationConfigmap = "migrate-db" - migrationsPath = "/migrate" - rootUserInternal = "root" - rootUserPath = "/certificates" - envMigrationUser = "FLYWAY_USER" - envMigrationPW = "FLYWAY_PASSWORD" - jobNamePrefix = "cockroachdb-cluster-migration-" - createFile = "create.sql" - grantFile = "grant.sql" - deleteFile = "delete.sql" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - reason string, - secretPasswordName string, - migrationUser string, - users []string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - customImageRegistry string, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("type", "migration") - jobName := getJobName(reason) - - destroyCM, err := configmap.AdaptFuncToDestroy(namespace, migrationConfigmap) - if err != nil { - return nil, nil, err - } - - destroyJ, err := job.AdaptFuncToDestroy(namespace, jobName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyJ), - operator.ResourceDestroyToZitadelDestroy(destroyCM), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - dbCurrent, err := database.GetDatabaseInQueried(queried) - if err != nil { - return nil, err - } - dbHost := dbCurrent.Host - dbPort := dbCurrent.Port - - allScripts := getMigrationFiles(monitor, "/cockroach/") - - nameLabels := labels.MustForNameK8SMap(componentLabels, jobName) - jobDef := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName, - Namespace: namespace, - Labels: nameLabels, - Annotations: map[string]string{ - "migrationhash": getHash(allScripts), - }, - }, - Spec: batchv1.JobSpec{ - Completions: helpers.PointerInt32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - "migrationhash": getHash(allScripts), - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName, customImageRegistry), - Containers: []corev1.Container{ - getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users, customImageRegistry), - }, - RestartPolicy: "Never", - DNSPolicy: "ClusterFirst", - SchedulerName: "default-scheduler", - TerminationGracePeriodSeconds: helpers.PointerInt64(30), - Volumes: []corev1.Volume{{ - Name: migrationConfigmap, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: migrationConfigmap}, - }, - }, - }, { - Name: rootUserInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.root", - DefaultMode: helpers.PointerInt32(0400), - }, - }, - }, { - Name: secretPasswordName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretPasswordName, - }, - }, - }}, - }, - }, - }, - } - - allScriptsMap := make(map[string]string) - for _, script := range allScripts { - allScriptsMap[script.Filename] = script.Data - } - queryCM, err := configmap.AdaptFuncToEnsure(namespace, migrationConfigmap, labels.MustForNameK8SMap(componentLabels, migrationConfigmap), allScriptsMap) - if err != nil { - return nil, err - } - queryJ, err := job.AdaptFuncToEnsure(jobDef) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryCM), - operator.ResourceQueryToZitadelQuery(queryJ), - } - return operator.QueriersToEnsureFunc(internalMonitor, true, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil -} - -func baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret string) []corev1.EnvVar { - envVars := []corev1.EnvVar{ - { - Name: envMigrationUser, - Value: migrationUser, - }, { - Name: envMigrationPW, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: migrationUser, - }, - }, - }, - } - return envVars -} - -func getHash(dataMap []migration) string { - data, err := json.Marshal(dataMap) - if err != nil { - return "" - } - h := sha512.New() - return base64.URLEncoding.EncodeToString(h.Sum(data)) -} - -type migration struct { - Filename string - Data string -} - -const migrationFileRegex = `(V|U)(\.|\d)+(__)(\w|\_|\ )+(\.sql)` - -func getMigrationFiles(monitor mntr.Monitor, root string) []migration { - migrations := make([]migration, 0) - files := []string{} - /* - absPath, err := filepath.Abs(root) - if err != nil { - return migrations - }*/ - - statikFS, err := fs.New() - if err != nil { - monitor.Error(fmt.Errorf("failed to load migration files: %w", err)) - return migrations - } - err = fs.Walk(statikFS, root, func(path string, info os.FileInfo, err error) error { - matched, err := regexp.MatchString(migrationFileRegex, info.Name()) - if err != nil { - return err - } - if !info.IsDir() && matched { - files = append(files, info.Name()) - } - return nil - }) - if err != nil { - panic(err) - } - sort.Strings(files) - - for _, file := range files { - - fullName := filepath.Join(root, file) - - data, err := fs.ReadFile(statikFS, fullName) - if err != nil || data == nil || len(data) == 0 { - continue - } - migrations = append(migrations, migration{file, string(data)}) - } - - return migrations -} - -func getJobName(reason string) string { - return jobNamePrefix + reason -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/migration/adapt_test.go deleted file mode 100644 index 488cdd8d67..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/adapt_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package migration - -import ( - "testing" - - "github.com/caos/orbos/pkg/labels" - - "github.com/caos/orbos/pkg/labels/mocklabels" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/zitadel/operator/helpers" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestMigration_BaseEnvVars(t *testing.T) { - envMigrationUser := "envmigration" - migrationUser := "migration" - envMigrationPW := "migration" - userPasswordsSecret := "passwords" - - equals := []corev1.EnvVar{ - { - Name: envMigrationUser, - Value: migrationUser, - }, { - Name: envMigrationPW, - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: migrationUser, - }, - }, - }, - } - - envVars := baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret) - assert.ElementsMatch(t, envVars, equals) -} - -func TestMigration_GetMigrationFiles(t *testing.T) { - equals := []migration{ - { - Filename: "V1.1__test.sql", - Data: "test", - }, - - { - Filename: "V1.2__test2.sql", - Data: "test2", - }, - } - - files := getMigrationFiles(mntr.Monitor{}, "/testfiles/") - assert.ElementsMatch(t, equals, files) -} - -func TestMigration_AdaptFunc(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - secretPasswordName := "test" - migrationUser := "migration" - users := []string{"test"} - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - dbHost := "test" - dbPort := "test" - - allScripts := getMigrationFiles(mntr.Monitor{}, "/cockroach/") - - componentLabels := mocklabels.Component - jobName := labels.MustForName(componentLabels, jobNamePrefix+reason) - - jobDef := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(jobName), - Annotations: map[string]string{ - "migrationhash": getHash(allScripts), - }, - }, - Spec: batchv1.JobSpec{ - Completions: helpers.PointerInt32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - "migrationhash": getHash(allScripts), - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName, ""), - Containers: []corev1.Container{ - getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users, ""), - }, - RestartPolicy: "Never", - DNSPolicy: "ClusterFirst", - SchedulerName: "default-scheduler", - TerminationGracePeriodSeconds: helpers.PointerInt64(30), - Volumes: []corev1.Volume{{ - Name: migrationConfigmap, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: migrationConfigmap}, - }, - }, - }, { - Name: rootUserInternal, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cockroachdb.client.root", - DefaultMode: helpers.PointerInt32(0400), - }, - }, - }, { - Name: secretPasswordName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretPasswordName, - }, - }, - }}, - }, - }, - }, - } - - allScriptsMap := make(map[string]string) - for _, script := range allScripts { - allScriptsMap[script.Filename] = script.Data - } - - cmName := labels.MustForName(componentLabels, migrationConfigmap) - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: cmName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(cmName), - }, - Data: allScriptsMap, - } - client.EXPECT().ApplyJob(jobDef).Times(1) - client.EXPECT().GetJob(namespace, getJobName(reason)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobNamePrefix+reason)) - client.EXPECT().ApplyConfigmap(cm).Times(1) - - query, _, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - namespace, - reason, - secretPasswordName, - migrationUser, - users, - nodeselector, - tolerations, - "", - ) - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: dbHost, - Port: dbPort, - }) - - assert.NoError(t, err) - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) - -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/cleanup.go b/operator/zitadel/kinds/iam/zitadel/migration/cleanup.go deleted file mode 100644 index bacfa1e0c2..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/cleanup.go +++ /dev/null @@ -1,24 +0,0 @@ -package migration - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/zitadel/operator" -) - -func GetCleanupFunc( - monitor mntr.Monitor, - namespace string, - reason string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("cleanup migration job") - if err := k8sClient.DeleteJob(namespace, getJobName(reason)); err != nil { - return fmt.Errorf("error during job deletion: %w", err) - } - monitor.Info("migration cleanup is completed") - return nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/cleanup_test.go b/operator/zitadel/kinds/iam/zitadel/migration/cleanup_test.go deleted file mode 100644 index a950cb80e6..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/cleanup_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package migration - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestMigration_Cleanup1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().DeleteJob(namespace, getJobName(reason)).Times(1).Return(nil) - cleanupFunc := GetCleanupFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestMigration_Cleanup2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().DeleteJob(namespace, getJobName(reason)).Times(1).Return(nil) - cleanupFunc := GetCleanupFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestMigration_CleanupFailure1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().DeleteJob(namespace, getJobName(reason)).Times(1).Return(errors.New("failed")) - cleanupFunc := GetCleanupFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.Error(t, cleanupFunc(client)) -} - -func TestMigration_CleanupFailure2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().DeleteJob(namespace, getJobName(reason)).Times(1).Return(errors.New("failed")) - cleanupFunc := GetCleanupFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.Error(t, cleanupFunc(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/done.go b/operator/zitadel/kinds/iam/zitadel/migration/done.go deleted file mode 100644 index a28058fa2a..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/done.go +++ /dev/null @@ -1,30 +0,0 @@ -package migration - -import ( - "fmt" - "time" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - - "github.com/caos/zitadel/operator" -) - -const ( - timeout = 20 * time.Minute -) - -func GetDoneFunc( - monitor mntr.Monitor, - namespace string, - reason string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for migration to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, getJobName(reason), timeout); err != nil { - return fmt.Errorf("error while waiting for migration to be completed: %w", err) - } - monitor.Info("migration is completed") - return nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/done_test.go b/operator/zitadel/kinds/iam/zitadel/migration/done_test.go deleted file mode 100644 index 2c39fad24d..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/done_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package migration - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestMigration_Done1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(nil) - cleanupFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestMigration_Done2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(nil) - cleanupFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestMigration_DoneFailure1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(errors.New("failed")) - doneFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, doneFunc) - assert.Error(t, doneFunc(client)) -} - -func TestMigration_DoneFailure2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(errors.New("failed")) - doneFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, doneFunc) - assert.Error(t, doneFunc(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer.go b/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer.go deleted file mode 100644 index d6a0bf6bf4..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer.go +++ /dev/null @@ -1,61 +0,0 @@ -package migration - -import ( - "strings" - - "github.com/caos/zitadel/operator/common" - - corev1 "k8s.io/api/core/v1" -) - -func getMigrationContainer( - dbHost string, - dbPort string, - migrationUser string, - secretPasswordName string, - users []string, - customImageRegistry string, -) corev1.Container { - - return corev1.Container{ - Name: "db-migration", - Image: common.FlywayImage.Reference(customImageRegistry), - Args: []string{ - "-url=jdbc:postgresql://" + dbHost + ":" + dbPort + "/defaultdb?&sslmode=verify-full&ssl=true&sslrootcert=" + rootUserPath + "/ca.crt&sslfactory=org.postgresql.ssl.NonValidatingFactory", - "-locations=filesystem:" + migrationsPath, - "migrate", - }, - Env: migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, secretPasswordName, users), - VolumeMounts: []corev1.VolumeMount{{ - Name: migrationConfigmap, - MountPath: migrationsPath, - }, { - Name: rootUserInternal, - MountPath: rootUserPath, - }}, - TerminationMessagePath: corev1.TerminationMessagePathDefault, - TerminationMessagePolicy: "File", - ImagePullPolicy: "IfNotPresent", - } -} - -func migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret string, users []string) []corev1.EnvVar { - envVars := baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret) - - migrationEnvVars := make([]corev1.EnvVar, 0) - for _, v := range envVars { - migrationEnvVars = append(migrationEnvVars, v) - } - for _, user := range users { - migrationEnvVars = append(migrationEnvVars, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user, - }, - }, - }) - } - return migrationEnvVars -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer_test.go b/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer_test.go deleted file mode 100644 index c2c8c78d4b..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/migrationcontainer_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package migration - -import ( - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "strings" - "testing" -) - -func TestMigration_MigrationsEnvVars(t *testing.T) { - - envMigrationUser := "envmigration" - migrationUser := "migration" - envMigrationPW := "migration" - userPasswordsSecret := "passwords" - user1 := "test" - users := []string{} - - baseEnv := baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret) - - equals := make([]corev1.EnvVar, 0) - for _, v := range baseEnv { - equals = append(equals, v) - } - - envVars := migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret, users) - assert.ElementsMatch(t, envVars, equals) - - users = []string{user1} - equals = make([]corev1.EnvVar, 0) - for _, v := range baseEnv { - equals = append(equals, v) - } - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user1) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user1, - }, - }, - }) - - envVars = migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret, users) - assert.ElementsMatch(t, envVars, equals) - - user2 := "test2" - users = []string{user1, user2} - - equals = make([]corev1.EnvVar, 0) - for _, v := range baseEnv { - equals = append(equals, v) - } - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user1) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user1, - }, - }, - }) - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user2) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user2, - }, - }, - }) - - envVars = migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret, users) - assert.ElementsMatch(t, envVars, equals) - - user3 := "test3" - users = []string{user1, user2, user3} - - equals = make([]corev1.EnvVar, 0) - for _, v := range baseEnv { - equals = append(equals, v) - } - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user1) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user1, - }, - }, - }) - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user2) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user2, - }, - }, - }) - equals = append(equals, corev1.EnvVar{ - Name: "FLYWAY_PLACEHOLDERS_" + strings.ToUpper(user3) + "PASSWORD", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: userPasswordsSecret}, - Key: user3, - }, - }, - }) - - envVars = migrationEnvVars(envMigrationUser, envMigrationPW, migrationUser, userPasswordsSecret, users) - assert.ElementsMatch(t, envVars, equals) -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/postcontainer.go b/operator/zitadel/kinds/iam/zitadel/migration/postcontainer.go deleted file mode 100644 index 06d245f3a1..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/postcontainer.go +++ /dev/null @@ -1,48 +0,0 @@ -package migration - -import ( - "strings" - - "github.com/caos/zitadel/operator/common" - - corev1 "k8s.io/api/core/v1" -) - -func getPostContainers( - dbHost string, - dbPort string, - migrationUser string, - secretPasswordName string, - customImageRegistry string, -) []corev1.Container { - - return []corev1.Container{ - { - Name: "delete-flyway-user", - Image: common.CockroachImage.Reference(customImageRegistry), - Command: []string{"/bin/bash", "-c", "--"}, - Args: []string{ - strings.Join([]string{ - deleteUserCommand(envMigrationUser, deleteFile), - "cockroach.sh sql --certs-dir=/certificates --host=" + dbHost + ":" + dbPort + " -e \"$(cat " + deleteFile + ")\";", - }, ";"), - }, - Env: baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, secretPasswordName), - VolumeMounts: []corev1.VolumeMount{{ - Name: rootUserInternal, - MountPath: rootUserPath, - }}, - TerminationMessagePath: corev1.TerminationMessagePathDefault, - TerminationMessagePolicy: "File", - ImagePullPolicy: "IfNotPresent", - }, - } -} - -func deleteUserCommand(user, file string) string { - return strings.Join([]string{ - "echo -n 'DROP USER IF EXISTS ' > " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ';' >> " + file, - }, ";") -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/postcontainer_test.go b/operator/zitadel/kinds/iam/zitadel/migration/postcontainer_test.go deleted file mode 100644 index bb9e93f64e..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/postcontainer_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package migration - -import ( - "github.com/stretchr/testify/assert" - "strings" - "testing" -) - -func TestMigration_DropUserCommand(t *testing.T) { - user := "test" - file := "test" - equals := strings.Join([]string{ - "echo -n 'DROP USER IF EXISTS ' > " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ';' >> " + file, - }, ";") - - cmd := deleteUserCommand(user, file) - assert.Equal(t, cmd, equals) -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/precontainer.go b/operator/zitadel/kinds/iam/zitadel/migration/precontainer.go deleted file mode 100644 index 584279be92..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/precontainer.go +++ /dev/null @@ -1,87 +0,0 @@ -package migration - -import ( - "strings" - - "github.com/caos/zitadel/operator/common" - - corev1 "k8s.io/api/core/v1" -) - -func getPreContainer( - dbHost string, - dbPort string, - migrationUser string, - secretPasswordName string, - customImageRegistry string, -) []corev1.Container { - - return []corev1.Container{ - { - Name: "check-db-ready", - Image: common.PostgresImage.Reference(customImageRegistry), - Command: []string{ - "sh", - "-c", - "until pg_isready -h " + dbHost + " -p " + dbPort + "; do echo waiting for database; sleep 2; done;", - }, - TerminationMessagePath: corev1.TerminationMessagePathDefault, - TerminationMessagePolicy: "File", - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "create-flyway-user", - Image: common.CockroachImage.Reference(customImageRegistry), - Env: baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, secretPasswordName), - VolumeMounts: []corev1.VolumeMount{{ - Name: rootUserInternal, - MountPath: rootUserPath, - }}, - Command: []string{"/bin/bash", "-c", "--"}, - Args: []string{ - strings.Join([]string{ - createUserCommand(envMigrationUser, envMigrationPW, createFile), - grantUserCommand(envMigrationUser, grantFile), - "cockroach.sh sql --certs-dir=/certificates --host=" + dbHost + ":" + dbPort + " -e \"$(cat " + createFile + ")\" -e \"$(cat " + grantFile + ")\";", - }, - ";"), - }, - TerminationMessagePath: corev1.TerminationMessagePathDefault, - TerminationMessagePolicy: "File", - ImagePullPolicy: "IfNotPresent", - }, - } -} - -func createUserCommand(user, pw, file string) string { - if user == "" || file == "" { - return "" - } - - createUser := strings.Join([]string{ - "echo -n 'CREATE USER IF NOT EXISTS ' > " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ';' >> " + file, - }, ";") - - if pw != "" { - createUser = strings.Join([]string{ - createUser, - "echo -n 'ALTER USER ' >> " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ' WITH PASSWORD ' >> " + file, - "echo -n ${" + pw + "} >> " + file, - "echo -n ';' >> " + file, - }, ";") - } - - return createUser -} - -func grantUserCommand(user, file string) string { - return strings.Join([]string{ - "echo -n 'GRANT admin TO ' > " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ' WITH ADMIN OPTION;' >> " + file, - }, ";") -} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/precontainer_test.go b/operator/zitadel/kinds/iam/zitadel/migration/precontainer_test.go deleted file mode 100644 index 8b2d51e862..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/migration/precontainer_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package migration - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMigration_CreateUserCommand(t *testing.T) { - user := "test" - pw := "test" - file := "test" - equals := "echo -n 'CREATE USER IF NOT EXISTS ' > " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ';' >> " + file + ";echo -n 'ALTER USER ' >> " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ' WITH PASSWORD ' >> " + file + ";echo -n ${" + pw + "} >> " + file + ";echo -n ';' >> " + file - - cmd := createUserCommand(user, pw, file) - assert.Equal(t, cmd, equals) - - user = "test1" - pw = "test1" - file = "test1" - equals = "echo -n 'CREATE USER IF NOT EXISTS ' > " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ';' >> " + file + ";echo -n 'ALTER USER ' >> " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ' WITH PASSWORD ' >> " + file + ";echo -n ${" + pw + "} >> " + file + ";echo -n ';' >> " + file - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, equals) - - user = "test2" - pw = "test2" - file = "test2" - equals = "echo -n 'CREATE USER IF NOT EXISTS ' > " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ';' >> " + file + ";echo -n 'ALTER USER ' >> " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ' WITH PASSWORD ' >> " + file + ";echo -n ${" + pw + "} >> " + file + ";echo -n ';' >> " + file - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, equals) - - user = "test" - pw = "" - file = "test" - equals = "echo -n 'CREATE USER IF NOT EXISTS ' > " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ';' >> " + file - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, equals) - - user = "test2" - pw = "" - file = "test2" - equals = "echo -n 'CREATE USER IF NOT EXISTS ' > " + file + ";echo -n ${" + user + "} >> " + file + ";echo -n ';' >> " + file - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, equals) - - user = "test2" - pw = "" - file = "" - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, "") - - user = "" - pw = "" - file = "test" - - cmd = createUserCommand(user, pw, file) - assert.Equal(t, cmd, "") - -} - -func TestMigration_GrantUserCommand(t *testing.T) { - user := "test" - file := "test" - equals := strings.Join([]string{ - "echo -n 'GRANT admin TO ' > " + file, - "echo -n ${" + user + "} >> " + file, - "echo -n ' WITH ADMIN OPTION;' >> " + file, - }, ";") - - cmd := grantUserCommand(user, file) - assert.Equal(t, cmd, equals) -} diff --git a/operator/zitadel/kinds/iam/zitadel/secrets.go b/operator/zitadel/kinds/iam/zitadel/secrets.go deleted file mode 100644 index 5c551f4d9a..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/secrets.go +++ /dev/null @@ -1,152 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/pkg/secret" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -func getSecretsMap(desiredKind *DesiredV0) ( - map[string]*secret.Secret, - map[string]*secret.Existing, -) { - - var ( - secrets = map[string]*secret.Secret{} - existing = map[string]*secret.Existing{} - ) - - if desiredKind.Spec == nil { - desiredKind.Spec = &Spec{} - } - - if desiredKind.Spec.Configuration == nil { - desiredKind.Spec.Configuration = &configuration.Configuration{} - } - - conf := desiredKind.Spec.Configuration - - if conf.Tracing == nil { - conf.Tracing = &configuration.Tracing{} - } - if conf.Tracing.ServiceAccountJSON == nil { - conf.Tracing.ServiceAccountJSON = &secret.Secret{} - } - if conf.Tracing.ExistingServiceAccountJSON == nil { - conf.Tracing.ExistingServiceAccountJSON = &secret.Existing{} - } - sakey := "tracingserviceaccountjson" - secrets[sakey] = conf.Tracing.ServiceAccountJSON - existing[sakey] = conf.Tracing.ExistingServiceAccountJSON - - if conf.Secrets == nil { - conf.Secrets = &configuration.Secrets{} - } - - if conf.Secrets.Keys == nil { - conf.Secrets.Keys = &secret.Secret{} - } - if conf.Secrets.ExistingKeys == nil { - conf.Secrets.ExistingKeys = &secret.Existing{} - } - keysKey := "keys" - secrets[keysKey] = conf.Secrets.Keys - existing[keysKey] = conf.Secrets.ExistingKeys - - if conf.Notifications == nil { - conf.Notifications = &configuration.Notifications{} - } - - if conf.Notifications.GoogleChatURL == nil { - conf.Notifications.GoogleChatURL = &secret.Secret{} - } - if conf.Notifications.ExistingGoogleChatURL == nil { - conf.Notifications.ExistingGoogleChatURL = &secret.Existing{} - } - gchatkey := "googlechaturl" - secrets[gchatkey] = conf.Notifications.GoogleChatURL - existing[gchatkey] = conf.Notifications.ExistingGoogleChatURL - - if conf.Notifications.Twilio == nil { - conf.Notifications.Twilio = &configuration.Twilio{} - } - if conf.Notifications.Twilio.SID == nil { - conf.Notifications.Twilio.SID = &secret.Secret{} - } - if conf.Notifications.Twilio.ExistingSID == nil { - conf.Notifications.Twilio.ExistingSID = &secret.Existing{} - } - twilKey := "twiliosid" - secrets[twilKey] = conf.Notifications.Twilio.SID - existing[twilKey] = conf.Notifications.Twilio.ExistingSID - - if conf.Notifications.Twilio.AuthToken == nil { - conf.Notifications.Twilio.AuthToken = &secret.Secret{} - } - if conf.Notifications.Twilio.ExistingAuthToken == nil { - conf.Notifications.Twilio.ExistingAuthToken = &secret.Existing{} - } - twilOAuthKey := "twilioauthtoken" - secrets[twilOAuthKey] = conf.Notifications.Twilio.AuthToken - existing[twilOAuthKey] = conf.Notifications.Twilio.ExistingAuthToken - - if conf.Notifications.Email == nil { - conf.Notifications.Email = &configuration.Email{} - } - if conf.Notifications.Email.AppKey == nil { - conf.Notifications.Email.AppKey = &secret.Secret{} - } - if conf.Notifications.Email.ExistingAppKey == nil { - conf.Notifications.Email.ExistingAppKey = &secret.Existing{} - } - mailKey := "emailappkey" - secrets[mailKey] = conf.Notifications.Email.AppKey - existing[mailKey] = conf.Notifications.Email.ExistingAppKey - - if conf.AssetStorage == nil { - conf.AssetStorage = &configuration.AssetStorage{} - } - if conf.AssetStorage.AccessKeyID == nil { - conf.AssetStorage.AccessKeyID = &secret.Secret{} - } - if conf.AssetStorage.ExistingAccessKeyID == nil { - conf.AssetStorage.ExistingAccessKeyID = &secret.Existing{} - } - if conf.AssetStorage.SecretAccessKey == nil { - conf.AssetStorage.SecretAccessKey = &secret.Secret{} - } - if conf.AssetStorage.ExistingSecretAccessKey == nil { - conf.AssetStorage.ExistingSecretAccessKey = &secret.Existing{} - } - accessKey := "accesskeyid" - secrets[accessKey] = conf.AssetStorage.AccessKeyID - existing[accessKey] = conf.AssetStorage.ExistingAccessKeyID - - secretKey := "secretaccesskey" - secrets[secretKey] = conf.AssetStorage.SecretAccessKey - existing[secretKey] = conf.AssetStorage.ExistingSecretAccessKey - - if conf.Proxy == nil { - conf.Proxy = &configuration.Proxy{} - } - if conf.Proxy.HTTP == nil { - conf.Proxy.HTTP = &secret.Secret{} - } - if conf.Proxy.ExistingHTTP == nil { - conf.Proxy.ExistingHTTP = &secret.Existing{} - } - if conf.Proxy.HTTPS == nil { - conf.Proxy.HTTPS = &secret.Secret{} - } - if conf.Proxy.ExistingHTTPS == nil { - conf.Proxy.ExistingHTTPS = &secret.Existing{} - } - httpProxy := "httpproxy" - secrets[httpProxy] = conf.Proxy.HTTP - existing[httpProxy] = conf.Proxy.ExistingHTTP - - httpsProxy := "httpsproxy" - secrets[httpsProxy] = conf.Proxy.HTTPS - existing[httpsProxy] = conf.Proxy.ExistingHTTPS - - return secrets, existing -} diff --git a/operator/zitadel/kinds/iam/zitadel/services/adapt.go b/operator/zitadel/kinds/iam/zitadel/services/adapt.go deleted file mode 100644 index f1939bf1e2..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/services/adapt.go +++ /dev/null @@ -1,86 +0,0 @@ -package services - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/service" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - zitadelPodSelector *labels.Selector, - namespace string, - grpcServiceName string, - grpcPort uint16, - httpServiceName string, - httpPort uint16, - uiServiceName string, - uiPort uint16, -) ( - operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("component", "services") - - destroyGRPC, err := service.AdaptFuncToDestroy(namespace, grpcServiceName) - if err != nil { - return nil, nil, err - } - - destroyHTTP, err := service.AdaptFuncToDestroy(namespace, httpServiceName) - if err != nil { - return nil, nil, err - } - - destroyUI, err := service.AdaptFuncToDestroy(namespace, uiServiceName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyGRPC), - operator.ResourceDestroyToZitadelDestroy(destroyHTTP), - operator.ResourceDestroyToZitadelDestroy(destroyUI), - } - - grpcPorts := []service.Port{ - {Name: "grpc", Port: grpcPort, TargetPort: "grpc"}, - } - queryGRPC, err := service.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, grpcServiceName), grpcPorts, "", zitadelPodSelector, false, "", "") - if err != nil { - return nil, nil, err - } - - httpPorts := []service.Port{ - {Name: "http", Port: httpPort, TargetPort: "http"}, - } - queryHTTP, err := service.AdaptFuncToEnsure(namespace, labels.AsSelectable(labels.MustForName(componentLabels, httpServiceName)), httpPorts, "", zitadelPodSelector, false, "", "") - if err != nil { - return nil, nil, err - } - - uiPorts := []service.Port{ - {Name: "ui", Port: uiPort, TargetPort: "ui"}, - } - queryUI, err := service.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, uiServiceName), uiPorts, "", zitadelPodSelector, false, "", "") - if err != nil { - return nil, nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(queryGRPC), - operator.ResourceQueryToZitadelQuery(queryHTTP), - operator.ResourceQueryToZitadelQuery(queryUI), - } - - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - - nil -} diff --git a/operator/zitadel/kinds/iam/zitadel/services/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/services/adapt_test.go deleted file mode 100644 index 4cf2f225d9..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/services/adapt_test.go +++ /dev/null @@ -1,418 +0,0 @@ -package services - -import ( - "testing" - - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "gotest.tools/assert" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func GetExpectedService( - namespace string, - zitadelPodSelector *labels.Selector, - grpcPortName string, - grpcServiceName *labels.Name, - grpcPort int, - httpPortName string, - httpServiceName *labels.Name, - httpPort int, - uiPortName string, - uiServiceName *labels.Name, - uiPort int, -) []*corev1.Service { - - grpcPorts := []corev1.ServicePort{{ - Name: grpcPortName, - Protocol: "", - Port: int32(grpcPort), - TargetPort: intstr.Parse(grpcPortName), - NodePort: int32(0), - }, - } - - httpPorts := []corev1.ServicePort{{ - Name: httpPortName, - Protocol: "", - Port: int32(httpPort), - TargetPort: intstr.Parse(httpPortName), - NodePort: int32(0), - }, - } - - uiPorts := []corev1.ServicePort{{ - Name: uiPortName, - Protocol: "", - Port: int32(uiPort), - TargetPort: intstr.Parse(uiPortName), - NodePort: int32(0), - }, - } - - zitadelPodSelectorMap := labels.MustK8sMap(zitadelPodSelector) - - return []*corev1.Service{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: grpcServiceName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(grpcServiceName), - }, - Spec: corev1.ServiceSpec{ - Ports: grpcPorts, - Selector: zitadelPodSelectorMap, - Type: "", - PublishNotReadyAddresses: false, - ClusterIP: "", - ExternalName: "", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: httpServiceName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(labels.AsSelectable(httpServiceName)), - }, - Spec: corev1.ServiceSpec{ - Ports: httpPorts, - Selector: zitadelPodSelectorMap, - Type: "", - PublishNotReadyAddresses: false, - ClusterIP: "", - ExternalName: "", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: uiServiceName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(uiServiceName), - }, - Spec: corev1.ServiceSpec{ - Ports: uiPorts, - Selector: zitadelPodSelectorMap, - Type: "", - PublishNotReadyAddresses: false, - ClusterIP: "", - ExternalName: "", - }, - }, - } -} - -func serviceLabels(name ...string) (*labels.Component, *labels.Selector, []*labels.Name) { - componentLabels := mocklabels.Component - podSelectorLabels := labels.DeriveNameSelector(labels.MustForName(componentLabels, "zitadel"), false) - nameLabels := make([]*labels.Name, len(name)) - for idx := range name { - nameLabels[idx] = labels.MustForName(componentLabels, name[idx]) - } - return componentLabels, podSelectorLabels, nameLabels -} - -func TestServices_AdaptEnsure1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test" - grpcPortName := "grpc" - grpcServiceName := "grpc" - grpcPort := 1 - httpPortName := "http" - httpServiceName := "http" - httpPort := 2 - uiPortName := "ui" - uiServiceName := "ui" - uiPort := 3 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - client.EXPECT().ApplyService(rsc).Times(1) - } - - query, _, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort), - ) - - assert.NilError(t, err) - ensure, err := query(client, nil) - assert.NilError(t, err) - assert.NilError(t, ensure(client)) -} - -func TestServices_AdaptEnsure2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test0" - grpcPortName := "grpc" - grpcServiceName := "grpc1" - grpcPort := 11 - httpPortName := "http" - httpServiceName := "http2" - httpPort := 22 - uiPortName := "ui" - uiServiceName := "ui3" - uiPort := 33 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - - client.EXPECT().ApplyService(rsc).Times(1) - } - - query, _, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - - assert.NilError(t, err) - ensure, err := query(client, nil) - assert.NilError(t, err) - assert.NilError(t, ensure(client)) -} - -func TestServices_AdaptEnsure3(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test00" - grpcPortName := "grpc" - grpcServiceName := "grpc11" - grpcPort := 111 - httpPortName := "http" - httpServiceName := "http22" - httpPort := 222 - uiPortName := "ui" - uiServiceName := "ui33" - uiPort := 333 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - - client.EXPECT().ApplyService(rsc).Times(1) - } - - query, _, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - - assert.NilError(t, err) - ensure, err := query(client, nil) - assert.NilError(t, err) - assert.NilError(t, ensure(client)) -} - -func TestServices_AdaptDestroy1(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test" - grpcPortName := "grpc" - grpcServiceName := "grpc" - grpcPort := 1 - httpPortName := "http" - httpServiceName := "http" - httpPort := 2 - uiPortName := "ui" - uiServiceName := "ui" - uiPort := 3 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - - client.EXPECT().DeleteService(rsc.Namespace, rsc.Name).Times(1) - } - - _, destroy, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - - assert.NilError(t, err) - assert.NilError(t, destroy(client)) -} - -func TestServices_AdaptDestroy2(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test0" - grpcPortName := "grpc" - grpcServiceName := "grpc1" - grpcPort := 11 - httpPortName := "http" - httpServiceName := "http2" - httpPort := 22 - uiPortName := "ui" - uiServiceName := "ui3" - uiPort := 33 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - - client.EXPECT().DeleteService(rsc.Namespace, rsc.Name).Times(1) - } - - _, destroy, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - - assert.NilError(t, err) - assert.NilError(t, destroy(client)) -} - -func TestServices_AdaptDestroy3(t *testing.T) { - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - - namespace := "test00" - grpcPortName := "grpc" - grpcServiceName := "grpc11" - grpcPort := 111 - httpPortName := "http" - httpServiceName := "http22" - httpPort := 222 - uiPortName := "ui" - uiServiceName := "ui33" - uiPort := 333 - - componentLabels, podSelectorLabels, nameLabels := serviceLabels(grpcServiceName, httpServiceName, uiServiceName) - - for _, rsc := range GetExpectedService( - namespace, - podSelectorLabels, - grpcPortName, - nameLabels[0], - grpcPort, - httpPortName, - nameLabels[1], - httpPort, - uiPortName, - nameLabels[2], - uiPort, - ) { - - client.EXPECT().DeleteService(rsc.Namespace, rsc.Name).Times(1) - } - - _, destroy, err := AdaptFunc( - mntr.Monitor{}, - componentLabels, - podSelectorLabels, - namespace, - grpcServiceName, - uint16(grpcPort), - httpServiceName, - uint16(httpPort), - uiServiceName, - uint16(uiPort)) - - assert.NilError(t, err) - assert.NilError(t, destroy(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/services/clientid.go b/operator/zitadel/kinds/iam/zitadel/services/clientid.go deleted file mode 100644 index c64057a1bf..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/services/clientid.go +++ /dev/null @@ -1,27 +0,0 @@ -package services - -import ( - "io/ioutil" - "net/http" - "strconv" - "strings" -) - -func GetClientIDFunc( - namespace string, - httpServiceName string, - httpPort int, -) func() string { - return func() string { - resp, err := http.Get("http://" + httpServiceName + "." + namespace + ":" + strconv.Itoa(httpPort) + "/clientID") - if err != nil || resp.StatusCode >= 400 { - return "" - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "" - } - return strings.TrimSuffix(strings.TrimPrefix(string(body), "\""), "\"") - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/setup/adapt.go b/operator/zitadel/kinds/iam/zitadel/setup/adapt.go deleted file mode 100644 index 660bf8aad0..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/setup/adapt.go +++ /dev/null @@ -1,199 +0,0 @@ -package setup - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/k8s" - "github.com/caos/orbos/pkg/kubernetes/resources/job" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/helpers" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/deployment" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - jobNamePrefix = "zitadel-setup-" - containerName = "zitadel" - rootSecret = "client-root" - dbSecrets = "db-secrets" -) - -func AdaptFunc( - monitor mntr.Monitor, - componentLabels *labels.Component, - namespace string, - reason string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - resources *k8s.Resources, - version *string, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordsName string, - customImageRegistry string, -) ( - func( - necessaryUsers map[string]string, - getConfigurationHashes func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error), - ) operator.QueryFunc, - operator.DestroyFunc, - error, -) { - internalMonitor := monitor.WithField("component", "setup") - - jobName := getJobName(reason) - nameLabels := labels.MustForName(componentLabels, jobName) - - destroyJ, err := job.AdaptFuncToDestroy(namespace, jobName) - if err != nil { - return nil, nil, err - } - - destroyers := []operator.DestroyFunc{ - operator.ResourceDestroyToZitadelDestroy(destroyJ), - } - - return func( - necessaryUsers map[string]string, - getConfigurationHashes func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error), - ) operator.QueryFunc { - return func(k8sClient kubernetes.ClientInt, queried map[string]interface{}) (operator.EnsureFunc, error) { - users := make([]string, 0) - for user := range necessaryUsers { - users = append(users, user) - } - - jobDef := jobDef( - nameLabels, - users, - version, - resources, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - namespace, - nodeselector, - tolerations, - customImageRegistry, - ) - - hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers) - if err != nil { - return nil, err - } - if hashes != nil && len(hashes) != 0 { - for k, v := range hashes { - jobDef.Annotations[k] = v - jobDef.Spec.Template.Annotations[k] = v - } - } - - query, err := job.AdaptFuncToEnsure(jobDef) - if err != nil { - return nil, err - } - - queriers := []operator.QueryFunc{ - operator.ResourceQueryToZitadelQuery(query), - } - - return operator.QueriersToEnsureFunc(internalMonitor, false, queriers, k8sClient, queried) - } - }, - operator.DestroyersToDestroyFunc(internalMonitor, destroyers), - nil - -} - -func jobDef( - name *labels.Name, - users []string, - version *string, - resources *k8s.Resources, - cmName string, - certPath string, - secretName string, - secretPath string, - consoleCMName string, - secretVarsName string, - secretPasswordsName string, - namespace string, - nodeselector map[string]string, - tolerations []corev1.Toleration, - customImageRegistry string, -) *batchv1.Job { - initContainers := []corev1.Container{ - deployment.GetInitContainer( - rootSecret, - dbSecrets, - users, - deployment.RunAsUser, - customImageRegistry, - )} - - containers := []corev1.Container{ - deployment.GetContainer( - containerName, - *version, - deployment.RunAsUser, - true, - deployment.GetResourcesFromDefault(resources), - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - users, - dbSecrets, - "setup", - customImageRegistry, - )} - - volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users) - - return &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: name.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(name), - Annotations: map[string]string{}, - }, - Spec: batchv1.JobSpec{ - Completions: helpers.PointerInt32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{}, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - InitContainers: initContainers, - Containers: containers, - - RestartPolicy: "Never", - DNSPolicy: "ClusterFirst", - SchedulerName: "default-scheduler", - TerminationGracePeriodSeconds: helpers.PointerInt64(30), - Volumes: volumes, - }, - }, - }, - } -} - -func getJobName(reason string) string { - return jobNamePrefix + reason -} diff --git a/operator/zitadel/kinds/iam/zitadel/setup/adapt_test.go b/operator/zitadel/kinds/iam/zitadel/setup/adapt_test.go deleted file mode 100644 index 3439274f09..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/setup/adapt_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package setup - -import ( - "testing" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/k8s" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/labels/mocklabels" - "github.com/caos/zitadel/operator/helpers" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/deployment" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - macherrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestSetup_AdaptFunc(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - usersMap := map[string]string{"test": "test"} - users := []string{} - for _, user := range usersMap { - users = append(users, user) - } - nodeselector := map[string]string{"test": "test"} - tolerations := []corev1.Toleration{} - dbHost := "test" - dbPort := "test" - - version := "test" - secretVarsName := "testVars" - secretPasswordsName := "testPasswords" - secretPath := "testSecretPath" - certPath := "testCert" - secretName := "testSecret" - consoleCMName := "testConsoleCM" - cmName := "testCM" - annotations := map[string]string{"testHash": "test"} - - componentLabels := mocklabels.Component - - resources := &k8s.Resources{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("512Mi"), - }, - } - - initContainers := []corev1.Container{deployment.GetInitContainer(rootSecret, dbSecrets, users, deployment.RunAsUser, "")} - containers := []corev1.Container{deployment.GetContainer( - containerName, - version, - deployment.RunAsUser, - true, - resources, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - users, - dbSecrets, - "setup", - "", - )} - volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users) - - jobName := labels.MustForName(componentLabels, jobNamePrefix+reason) - jobDef := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - Name: jobName.Name(), - Namespace: namespace, - Labels: labels.MustK8sMap(jobName), - Annotations: annotations, - }, - Spec: batchv1.JobSpec{ - Completions: helpers.PointerInt32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: annotations, - }, - Spec: corev1.PodSpec{ - NodeSelector: nodeselector, - Tolerations: tolerations, - InitContainers: initContainers, - Containers: containers, - - RestartPolicy: "Never", - DNSPolicy: "ClusterFirst", - SchedulerName: "default-scheduler", - TerminationGracePeriodSeconds: helpers.PointerInt64(30), - Volumes: volumes, - }, - }, - }, - } - - client.EXPECT().ApplyJob(jobDef).Times(1) - client.EXPECT().GetJob(namespace, getJobName(reason)).Times(1).Return(nil, macherrs.NewNotFound(schema.GroupResource{"batch", "jobs"}, jobNamePrefix+reason)) - - getConfigurationHashes := func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, necessaryUsers map[string]string) (map[string]string, error) { - return map[string]string{"testHash": "test"}, nil - } - - getQuery, _, err := AdaptFunc( - monitor, - componentLabels, - namespace, - reason, - nodeselector, - tolerations, - resources, - &version, - cmName, - certPath, - secretName, - secretPath, - consoleCMName, - secretVarsName, - secretPasswordsName, - "", - ) - - queried := map[string]interface{}{} - database.SetDatabaseInQueried(queried, &database.Current{ - Host: dbHost, - Port: dbPort, - }) - - assert.NoError(t, err) - query := getQuery(usersMap, getConfigurationHashes) - ensure, err := query(client, queried) - assert.NoError(t, err) - assert.NoError(t, ensure(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/setup/done.go b/operator/zitadel/kinds/iam/zitadel/setup/done.go deleted file mode 100644 index a57249ef77..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/setup/done.go +++ /dev/null @@ -1,30 +0,0 @@ -package setup - -import ( - "fmt" - "time" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - - "github.com/caos/zitadel/operator" -) - -const ( - timeout = 20 * time.Minute -) - -func GetDoneFunc( - monitor mntr.Monitor, - namespace string, - reason string, -) operator.EnsureFunc { - return func(k8sClient kubernetes.ClientInt) error { - monitor.Info("waiting for setup to be completed") - if err := k8sClient.WaitUntilJobCompleted(namespace, getJobName(reason), timeout); err != nil { - return fmt.Errorf("error while waiting for setup to be completed: %w", err) - } - monitor.Info("migration is completed") - return nil - } -} diff --git a/operator/zitadel/kinds/iam/zitadel/setup/done_test.go b/operator/zitadel/kinds/iam/zitadel/setup/done_test.go deleted file mode 100644 index 1661b6048d..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/setup/done_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package setup - -import ( - "errors" - "github.com/caos/orbos/mntr" - kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestSetup_Done1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(nil) - cleanupFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestSetup_Done2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(nil) - cleanupFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, cleanupFunc) - assert.NoError(t, cleanupFunc(client)) -} - -func TestSetup_DoneFailure1(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test" - reason := "test" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(errors.New("failed")) - doneFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, doneFunc) - assert.Error(t, doneFunc(client)) -} - -func TestSetup_DoneFailure2(t *testing.T) { - monitor := mntr.Monitor{} - client := kubernetesmock.NewMockClientInt(gomock.NewController(t)) - namespace := "test2" - reason := "test2" - - client.EXPECT().WaitUntilJobCompleted(namespace, getJobName(reason), timeout).Times(1).Return(errors.New("failed")) - doneFunc := GetDoneFunc(monitor, namespace, reason) - assert.NotNil(t, doneFunc) - assert.Error(t, doneFunc(client)) -} diff --git a/operator/zitadel/kinds/iam/zitadel/users.go b/operator/zitadel/kinds/iam/zitadel/users.go deleted file mode 100644 index 3699751808..0000000000 --- a/operator/zitadel/kinds/iam/zitadel/users.go +++ /dev/null @@ -1,112 +0,0 @@ -package zitadel - -import ( - "sort" - - "github.com/caos/orbos/pkg/secret/read" - - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/secret" - - "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration" -) - -const ( - migrationUser = "flyway" - mgmtUser = "management" - adminUser = "adminapi" - authUser = "auth" - authzUser = "authz" - notUser = "notification" - esUser = "eventstore" - queriesUser = "queries" -) - -func getUserListWithoutPasswords(desired *DesiredV0) []string { - userpw, _ := getAllUsers(nil, desired) - users := make([]string, 0) - for user := range userpw { - users = append(users, user) - } - - sort.Slice(users, func(i, j int) bool { - return users[i] < users[j] - }) - return users -} - -func getAllUsers(k8sClient kubernetes.ClientInt, desired *DesiredV0) (map[string]string, error) { - passwords := &configuration.Passwords{} - if desired != nil && desired.Spec != nil && desired.Spec.Configuration != nil && desired.Spec.Configuration.Passwords != nil { - passwords = desired.Spec.Configuration.Passwords - } - users := make(map[string]string, 0) - - if err := fillInUserPassword(k8sClient, migrationUser, passwords.Migration, passwords.ExistingMigration, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, mgmtUser, passwords.Management, passwords.ExistingManagement, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, adminUser, passwords.Adminapi, passwords.ExistingAdminapi, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, authUser, passwords.Auth, passwords.ExistingAuth, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, authzUser, passwords.Authz, passwords.ExistingAuthz, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, notUser, passwords.Notification, passwords.ExistingNotification, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, esUser, passwords.Eventstore, passwords.ExistingEventstore, users); err != nil { - return nil, err - } - if err := fillInUserPassword(k8sClient, queriesUser, passwords.Queries, passwords.ExistingQueries, users); err != nil { - return nil, err - } - - return users, nil -} - -func fillInUserPassword( - k8sClient kubernetes.ClientInt, - user string, - secret *secret.Secret, - existing *secret.Existing, - userpw map[string]string, -) error { - if k8sClient == nil { - userpw[user] = user - return nil - } - - pw, err := read.GetSecretValue(k8sClient, secret, existing) - if err != nil { - return err - } - if pw != "" { - userpw[user] = pw - } else { - userpw[user] = user - } - - return nil -} - -func getZitadelUserList(k8sClient kubernetes.ClientInt, desired *DesiredV0) (map[string]string, error) { - allUsersMap, err := getAllUsers(k8sClient, desired) - if err != nil { - return nil, err - } - - allZitadelUsers := make(map[string]string, 0) - for k, v := range allUsersMap { - if k != migrationUser { - allZitadelUsers[k] = v - } - } - - return allZitadelUsers, nil -} diff --git a/operator/zitadel/kinds/orb/adapt.go b/operator/zitadel/kinds/orb/adapt.go deleted file mode 100644 index ac0cdaa3cf..0000000000 --- a/operator/zitadel/kinds/orb/adapt.go +++ /dev/null @@ -1,150 +0,0 @@ -package orb - -import ( - "fmt" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/kubernetes/resources/namespace" - "github.com/caos/orbos/pkg/orb" - "github.com/caos/orbos/pkg/secret" - "github.com/caos/orbos/pkg/tree" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/operator/zitadel/kinds/iam" - zitadeldb "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database" -) - -const ( - namespaceName = "caos-zitadel" -) - -func AdaptFunc( - orbconfig *orb.Orb, - action string, - binaryVersion *string, - gitops bool, - features []string, -) operator.AdaptFunc { - return func( - monitor mntr.Monitor, - desiredTree *tree.Tree, - currentTree *tree.Tree, - ) ( - queryFunc operator.QueryFunc, - destroyFunc operator.DestroyFunc, - configureFunc operator.ConfigureFunc, - allSecrets map[string]*secret.Secret, - allExisting map[string]*secret.Existing, - migrate bool, - err error, - ) { - defer func() { - if err != nil { - err = fmt.Errorf("building %s failed: %w", desiredTree.Common.Kind, err) - } - }() - - allSecrets = make(map[string]*secret.Secret) - allExisting = make(map[string]*secret.Existing) - - orbMonitor := monitor.WithField("kind", "orb") - - desiredKind, err := ParseDesiredV0(desiredTree) - if err != nil { - return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err) - } - desiredTree.Parsed = desiredKind - currentTree = &tree.Tree{} - - if desiredKind.Spec.Verbose && !orbMonitor.IsVerbose() { - orbMonitor = orbMonitor.Verbose() - } - - var dbClient zitadeldb.Client - if gitops { - dbClientT, err := zitadeldb.NewGitOpsClient(monitor, orbconfig.URL, orbconfig.Repokey) - if err != nil { - monitor.Error(err) - return nil, nil, nil, nil, nil, false, err - } - dbClient = dbClientT - } else { - dbClient = zitadeldb.NewCrdClient(monitor) - } - - operatorLabels := mustZITADELOperator(binaryVersion) - - queryNS, err := namespace.AdaptFuncToEnsure(namespaceName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - /*destroyNS, err := namespace.AdaptFuncToDestroy(namespaceName) - if err != nil { - return nil, nil, allSecrets, err - }*/ - - iamCurrent := &tree.Tree{} - queryIAM, destroyIAM, configureIAM, zitadelSecrets, zitadelExisting, migrateIAM, err := iam.Adapt( - orbMonitor, - operatorLabels, - desiredKind.IAM, - iamCurrent, - desiredKind.Spec.NodeSelector, - desiredKind.Spec.Tolerations, - dbClient, - namespaceName, - action, - &desiredKind.Spec.Version, - features, - desiredKind.Spec.CustomImageRegistry, - ) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - migrate = migrate || migrateIAM - secret.AppendSecrets("", allSecrets, zitadelSecrets, allExisting, zitadelExisting) - - rec, _ := Reconcile(monitor, desiredKind.Spec, gitops) - - destroyers := make([]operator.DestroyFunc, 0) - queriers := make([]operator.QueryFunc, 0) - for _, feature := range features { - switch feature { - case "iam", "migration", "scaleup", "scaledown": - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryNS), - queryIAM, - ) - destroyers = append(destroyers, destroyIAM) - case "operator": - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryNS), - operator.EnsureFuncToQueryFunc(rec), - ) - } - } - - currentTree.Parsed = &DesiredV0{ - Common: tree.NewCommon("zitadel.caos.ch/Orb", "v0", false), - IAM: iamCurrent, - } - - return func(k8sClient kubernetes.ClientInt, _ map[string]interface{}) (operator.EnsureFunc, error) { - queried := map[string]interface{}{} - monitor.WithField("queriers", len(queriers)).Info("Querying") - return operator.QueriersToEnsureFunc(monitor, true, queriers, k8sClient, queried) - }, - func(k8sClient kubernetes.ClientInt) error { - monitor.WithField("destroyers", len(queriers)).Info("Destroy") - return operator.DestroyersToDestroyFunc(monitor, destroyers)(k8sClient) - }, - func(k8sClient kubernetes.ClientInt, queried map[string]interface{}, gitops bool) error { - return configureIAM(k8sClient, queried, gitops) - }, - allSecrets, - allExisting, - migrate, - nil - } -} diff --git a/operator/zitadel/kinds/orb/desired.go b/operator/zitadel/kinds/orb/desired.go deleted file mode 100644 index 00c46a050e..0000000000 --- a/operator/zitadel/kinds/orb/desired.go +++ /dev/null @@ -1,39 +0,0 @@ -package orb - -import ( - "fmt" - - corev1 "k8s.io/api/core/v1" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/tree" -) - -type DesiredV0 struct { - Common *tree.Common `yaml:",inline"` - Spec *Spec `json:"spec" yaml:"spec"` - IAM *tree.Tree `json:"iam" yaml:"iam"` -} - -// +kubebuilder:object:generate=true -type Spec struct { - Verbose bool `json:"verbose" yaml:"verbose"` - NodeSelector map[string]string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"` - Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"` - Version string `json:"version,omitempty" yaml:"version,omitempty"` - SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"` - //Use this registry to pull container images from - //@default: - CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` -} - -func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) { - desiredKind := &DesiredV0{Common: desiredTree.Common} - - if err := desiredTree.Original.Decode(desiredKind); err != nil { - return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err)) - } - desiredKind.Common.OverwriteVersion("v0") - - return desiredKind, nil -} diff --git a/operator/zitadel/kinds/orb/labels.go b/operator/zitadel/kinds/orb/labels.go deleted file mode 100644 index cbe4bc4fc3..0000000000 --- a/operator/zitadel/kinds/orb/labels.go +++ /dev/null @@ -1,13 +0,0 @@ -package orb - -import "github.com/caos/orbos/pkg/labels" - -func mustZITADELOperator(binaryVersion *string) *labels.Operator { - - version := "unknown" - if binaryVersion != nil { - version = *binaryVersion - } - - return labels.MustForOperator("ZITADEL", "zitadel.caos.ch", version) -} diff --git a/operator/zitadel/kinds/orb/reconcile.go b/operator/zitadel/kinds/orb/reconcile.go deleted file mode 100644 index 99f0c11c74..0000000000 --- a/operator/zitadel/kinds/orb/reconcile.go +++ /dev/null @@ -1,50 +0,0 @@ -package orb - -import ( - "errors" - "fmt" - - "github.com/caos/orbos/mntr" - kubernetes2 "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/orbos/pkg/treelabels" - - "github.com/caos/zitadel/operator" - "github.com/caos/zitadel/pkg/kubernetes" -) - -func Reconcile( - monitor mntr.Monitor, - spec *Spec, - gitops bool, -) ( - operator.EnsureFunc, - operator.DestroyFunc, -) { - return func(k8sClient kubernetes2.ClientInt) (err error) { - recMonitor := monitor.WithField("version", spec.Version) - - if spec.Version == "" { - return mntr.ToUserError(errors.New("no version provided for self-reconciling")) - } - - if spec.SelfReconciling { - desiredTree := &tree.Tree{ - Common: tree.NewCommon("zitadel.caos.ch/Orb", "v0", false), - } - - if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { - return fmt.Errorf("failed to deploy zitadel-operator into k8s-cluster: %w", err) - } - recMonitor.Info("Applied zitadel-operator") - } - return nil - }, func(k8sClient kubernetes2.ClientInt) error { - if err := kubernetes.DestroyZitadelOperator(monitor, labels.MustForAPI(labels.NoopOperator("zitadel-operator"), "zitadel", "v0"), k8sClient, gitops); err != nil { - return fmt.Errorf("failed to destroy zitadel-operator in k8s-cluster: %w", err) - } - monitor.Info("Destroyed zitadel-operator") - return nil - } -} diff --git a/operator/zitadel/kinds/orb/zz_generated.deepcopy.go b/operator/zitadel/kinds/orb/zz_generated.deepcopy.go deleted file mode 100644 index bf8af31d1b..0000000000 --- a/operator/zitadel/kinds/orb/zz_generated.deepcopy.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !ignore_autogenerated - -/* - - -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. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package orb - -import ( - "k8s.io/api/core/v1" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Spec) DeepCopyInto(out *Spec) { - *out = *in - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]v1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. -func (in *Spec) DeepCopy() *Spec { - if in == nil { - return nil - } - out := new(Spec) - in.DeepCopyInto(out) - return out -} diff --git a/operator/zitadel/takeoff.go b/operator/zitadel/takeoff.go deleted file mode 100644 index 548e626f07..0000000000 --- a/operator/zitadel/takeoff.go +++ /dev/null @@ -1,46 +0,0 @@ -package zitadel - -import ( - "github.com/caos/zitadel/operator" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" -) - -func Takeoff( - monitor mntr.Monitor, - gitClient *git.Client, - adapt operator.AdaptFunc, - k8sClient *kubernetes.Client, -) func() error { - return func() error { - internalMonitor := monitor.WithField("operator", "zitadel") - internalMonitor.Info("Takeoff") - treeDesired, err := operator.Parse(gitClient, "zitadel.yml") - if err != nil { - monitor.Error(err) - return err - } - treeCurrent := &tree.Tree{} - - query, _, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) - if err != nil { - internalMonitor.Error(err) - return err - } - - ensure, err := query(k8sClient, map[string]interface{}{}) - if err != nil { - internalMonitor.Error(err) - return err - } - - if err := ensure(k8sClient); err != nil { - internalMonitor.Error(err) - return err - } - return nil - } -} diff --git a/pkg/databases/backup.go b/pkg/databases/backup.go deleted file mode 100644 index e038754416..0000000000 --- a/pkg/databases/backup.go +++ /dev/null @@ -1,63 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func GitOpsInstantBackup( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, - name string, -) error { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - return err - } - return instantBackup(monitor, k8sClient, desired, name) -} - -func CrdInstantBackup( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - name string, -) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return err - } - return instantBackup(monitor, k8sClient, desired, name) -} - -func instantBackup( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, - name string, -) error { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc(name, nil, false, "instantbackup")(monitor, desired, current) - if err != nil { - monitor.Error(err) - return err - } - - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - if err != nil { - monitor.Error(err) - return err - } - - if err := ensure(k8sClient); err != nil { - monitor.Error(err) - return err - } - return nil -} diff --git a/pkg/databases/backuplist.go b/pkg/databases/backuplist.go deleted file mode 100644 index 9ffedd953e..0000000000 --- a/pkg/databases/backuplist.go +++ /dev/null @@ -1,57 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func GitOpsListBackups( - monitor mntr.Monitor, - gitClient *git.Client, - k8sClient kubernetes.ClientInt, -) ( - []string, - error, -) { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - return nil, err - } - - return listBackups(monitor, k8sClient, desired) -} - -func CrdListBackups( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, -) ( - []string, - error, -) { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return nil, err - } - - return listBackups(monitor, k8sClient, desired) -} - -func listBackups( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, -) ( - []string, - error, -) { - backups, err := orbdb.BackupListFunc()(monitor, k8sClient, desired) - if err != nil { - return nil, err - } - - return backups, nil -} diff --git a/pkg/databases/clear.go b/pkg/databases/clear.go deleted file mode 100644 index 57d1d27313..0000000000 --- a/pkg/databases/clear.go +++ /dev/null @@ -1,61 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - "github.com/caos/zitadel/operator/database/kinds/databases/managed" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func GitOpsClear( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, -) error { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - return err - } - - return clear(monitor, k8sClient, desired, true) -} - -func CrdClear( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, -) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return err - } - - return clear(monitor, k8sClient, desired, false) -} - -func clear( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, - gitops bool, -) error { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, gitops, managed.Clean)(monitor, desired, current) - if err != nil { - return err - } - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - if err != nil { - return err - } - - if err := ensure(k8sClient); err != nil { - return err - } - - return nil -} diff --git a/pkg/databases/connection.go b/pkg/databases/connection.go deleted file mode 100644 index fae306930f..0000000000 --- a/pkg/databases/connection.go +++ /dev/null @@ -1,62 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - coredb "github.com/caos/zitadel/operator/database/kinds/databases/core" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func CrdGetConnectionInfo( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, -) (string, string, error) { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return "", "", err - } - - return getConnectionInfo(monitor, k8sClient, desired, false) -} - -func GitOpsGetConnectionInfo( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, -) (string, string, error) { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - monitor.Error(err) - return "", "", err - } - - return getConnectionInfo(monitor, k8sClient, desired, true) -} - -func getConnectionInfo( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, - gitOps bool, -) (string, string, error) { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, gitOps, "database")(monitor, desired, current) - if err != nil { - return "", "", err - } - - queried := map[string]interface{}{} - _, err = query(k8sClient, queried) - if err != nil { - return "", "", err - } - currentDB, err := coredb.ParseQueriedForDatabase(queried) - if err != nil { - return "", "", err - } - return currentDB.GetURL(), currentDB.GetPort(), nil -} diff --git a/pkg/databases/restore.go b/pkg/databases/restore.go deleted file mode 100644 index 7eb88f1b6c..0000000000 --- a/pkg/databases/restore.go +++ /dev/null @@ -1,62 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func GitOpsRestore( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, - name string, -) error { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - return err - } - return restore(monitor, k8sClient, desired, name) -} - -func CrdRestore( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - name string, -) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - return err - } - return restore(monitor, k8sClient, desired, name) -} - -func restore( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, - name string, -) error { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc(name, nil, false, "restore")(monitor, desired, current) - if err != nil { - monitor.Error(err) - return err - } - queried := map[string]interface{}{} - ensure, err := query(k8sClient, queried) - if err != nil { - monitor.Error(err) - return err - } - - if err := ensure(k8sClient); err != nil { - monitor.Error(err) - return err - } - return nil -} diff --git a/pkg/databases/user.go b/pkg/databases/user.go deleted file mode 100644 index 4266e77e8a..0000000000 --- a/pkg/databases/user.go +++ /dev/null @@ -1,195 +0,0 @@ -package databases - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/database" - coredb "github.com/caos/zitadel/operator/database/kinds/databases/core" - orbdb "github.com/caos/zitadel/operator/database/kinds/orb" -) - -func CrdListUsers( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, -) ([]string, error) { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - monitor.Error(err) - return nil, err - } - - return listUsers(monitor, k8sClient, desired) -} - -func GitOpsListUsers( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, -) ([]string, error) { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - monitor.Error(err) - return nil, err - } - - return listUsers(monitor, k8sClient, desired) -} - -func listUsers( - monitor mntr.Monitor, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, -) ([]string, error) { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, false, "database")(monitor, desired, current) - if err != nil { - return nil, err - } - - queried := map[string]interface{}{} - _, err = query(k8sClient, queried) - if err != nil { - return nil, err - } - currentDB, err := coredb.ParseQueriedForDatabase(queried) - if err != nil { - return nil, err - } - - list, err := currentDB.GetListUsersFunc()(k8sClient) - if err != nil { - return nil, err - } - - users := []string{} - for _, listedUser := range list { - if listedUser != "root" { - users = append(users, listedUser) - } - } - - return users, nil -} - -func CrdAddUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, -) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - monitor.Error(err) - return err - } - return addUser(monitor, user, k8sClient, desired) -} - -func GitOpsAddUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, -) error { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - monitor.Error(err) - return err - } - return addUser(monitor, user, k8sClient, desired) -} - -func addUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, -) error { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, false, "database")(monitor, desired, current) - if err != nil { - return err - } - - queried := map[string]interface{}{} - _, err = query(k8sClient, queried) - if err != nil { - return err - } - currentDB, err := coredb.ParseQueriedForDatabase(queried) - if err != nil { - return err - } - - queryUser, err := currentDB.GetAddUserFunc()(user) - if err != nil { - return err - } - ensureUser, err := queryUser(k8sClient, queried) - if err != nil { - return err - } - return ensureUser(k8sClient) -} - -func GitOpsDeleteUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, - gitClient *git.Client, -) error { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - monitor.Error(err) - return err - } - - return deleteUser(monitor, user, k8sClient, desired) -} - -func CrdDeleteUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, -) error { - desired, err := database.ReadCrd(k8sClient) - if err != nil { - monitor.Error(err) - return err - } - - return deleteUser(monitor, user, k8sClient, desired) -} - -func deleteUser( - monitor mntr.Monitor, - user string, - k8sClient kubernetes.ClientInt, - desired *tree.Tree, -) error { - current := &tree.Tree{} - - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, false, "database")(monitor, desired, current) - if err != nil { - return err - } - - queried := map[string]interface{}{} - _, err = query(k8sClient, queried) - if err != nil { - return err - } - currentDB, err := coredb.ParseQueriedForDatabase(queried) - if err != nil { - return err - } - - deleteUser, err := currentDB.GetDeleteUserFunc()(user) - if err != nil { - return err - } - return deleteUser(k8sClient) -} diff --git a/pkg/kubernetes/artifacts.go b/pkg/kubernetes/artifacts.go deleted file mode 100644 index 9a1c036f94..0000000000 --- a/pkg/kubernetes/artifacts.go +++ /dev/null @@ -1,703 +0,0 @@ -package kubernetes - -import ( - "github.com/caos/zitadel/operator/common" - - "gopkg.in/yaml.v3" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/kubernetes" - "github.com/caos/orbos/pkg/labels" - apps "k8s.io/api/apps/v1" - core "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/api/resource" - mach "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - namespace = "caos-system" -) - -func getZitadelOperatorNameLabels(apiLabels *labels.API) *labels.Name { - return toNameLabels(apiLabels, "zitadel-operator") -} - -func EnsureZitadelOperatorArtifacts( - monitor mntr.Monitor, - apiLabels *labels.API, - client kubernetes.ClientInt, - version string, - nodeselector map[string]string, - tolerations []core.Toleration, - customImageRegistry string, - gitops bool, -) error { - - monitor.WithFields(map[string]interface{}{ - "zitadel": version, - }).Debug("Ensuring zitadel artifacts") - - nameLabels := getZitadelOperatorNameLabels(apiLabels) - k8sNameLabels := labels.MustK8sMap(nameLabels) - k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) - - if version == "" { - return nil - } - - if err := client.ApplyServiceAccount(&core.ServiceAccount{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - }, - }); err != nil { - return err - } - - if err := client.ApplyClusterRole(&rbac.ClusterRole{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - Rules: []rbac.PolicyRule{{ - APIGroups: []string{"*"}, - Resources: []string{"*"}, - Verbs: []string{"*"}, - }}, - }); err != nil { - return err - } - - if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: nameLabels.Name(), - }, - Subjects: []rbac.Subject{{ - Kind: "ServiceAccount", - Name: nameLabels.Name(), - Namespace: namespace, - }}, - }); err != nil { - return err - } - - if !gitops { - crd := `apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null - name: zitadels.caos.ch -spec: - group: caos.ch - names: - kind: Zitadel - listKind: ZitadelList - plural: zitadels - singular: zitadel - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - apiVersion: - description: Don't access X_ApiVersion, it is only exported for (de-)serialization. - Use Version and OverwriteVersion methods instead. - type: string - iam: - type: object - kind: - type: string - spec: - properties: - customImageRegistry: - description: 'Use this registry to pull container images from - @default: ' - type: string - nodeSelector: - additionalProperties: - type: string - type: object - selfReconciling: - type: boolean - tolerations: - items: - description: The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - verbose: - type: boolean - version: - type: string - required: - - selfReconciling - - verbose - type: object - version: - description: Don't access X_Version, it is only exported for (de-)serialization. - Use Version and OverwriteVersion methods instead. - type: string - required: - - iam - - kind - - spec - type: object - status: - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: []` - - crdDefinition := &unstructured.Unstructured{} - if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { - return err - } - - if err := client.ApplyCRDResource( - crdDefinition, - ); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Database Operator crd ensured") - } - - var ( - cmd = []string{"/zitadelctl", "operator", "--kubeconfig", ""} - volumes []core.Volume - volumeMounts []core.VolumeMount - ) - - if gitops { - cmd = append(cmd, "--gitops", "-f", "/secrets/orbconfig") - volumes = []core.Volume{{ - Name: "orbconfig", - VolumeSource: core.VolumeSource{ - Secret: &core.SecretVolumeSource{ - SecretName: "caos", - }, - }, - }} - volumeMounts = []core.VolumeMount{{ - Name: "orbconfig", - ReadOnly: true, - MountPath: "/secrets", - }} - } - - if _, _, analyticsEnabled := mntr.Environment(); !analyticsEnabled { - cmd = append(cmd, "--disable-analytics") - } - - deployment := &apps.Deployment{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: k8sNameLabels, - }, - Spec: apps.DeploymentSpec{ - Replicas: int32Ptr(1), - Selector: &mach.LabelSelector{ - MatchLabels: k8sPodSelector, - }, - Template: core.PodTemplateSpec{ - ObjectMeta: mach.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - }, - Spec: core.PodSpec{ - ServiceAccountName: nameLabels.Name(), - Containers: []core.Container{{ - Name: "zitadel", - ImagePullPolicy: core.PullIfNotPresent, - Image: common.ZITADELOperatorImage.Reference(customImageRegistry, version), - Command: cmd, - Args: []string{}, - Ports: []core.ContainerPort{{ - Name: "metrics", - ContainerPort: 2112, - Protocol: "TCP", - }}, - VolumeMounts: volumeMounts, - Resources: core.ResourceRequirements{ - Limits: core.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("500Mi"), - }, - Requests: core.ResourceList{ - "cpu": resource.MustParse("250m"), - "memory": resource.MustParse("250Mi"), - }, - }, - }}, - NodeSelector: nodeselector, - Tolerations: tolerations, - Volumes: volumes, - TerminationGracePeriodSeconds: int64Ptr(10), - }, - }, - }, - } - if err := client.ApplyDeployment(deployment, true); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Zitadel Operator deployment ensured") - - return nil -} -func DestroyZitadelOperator( - monitor mntr.Monitor, - apiLabels *labels.API, - client kubernetes.ClientInt, - gitops bool, -) error { - nameLabels := getZitadelOperatorNameLabels(apiLabels) - - monitor.WithFields(map[string]interface{}{}).Debug("Destroying zitadel artifacts") - - if err := client.DeleteServiceAccount(namespace, nameLabels.Name()); err != nil { - return err - } - - if err := client.DeleteClusterRole(nameLabels.Name()); err != nil { - return err - } - - if err := client.DeleteClusterRoleBinding(nameLabels.Name()); err != nil { - return err - } - - if !gitops { - if err := client.DeleteCRDResource("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition", "zitadels.caos.ch"); err != nil { - return err - } - } - - if err := client.DeleteDeployment(namespace, nameLabels.Name()); err != nil { - return err - } - - return nil -} - -func ScaleZitadelOperator( - monitor mntr.Monitor, - client kubernetes.ClientInt, - replicaCount int, -) error { - monitor.Debug("Scaling zitadel-operator") - return client.ScaleDeployment(namespace, "zitadel-operator", replicaCount) -} - -func ScaleDatabaseOperator( - monitor mntr.Monitor, - client kubernetes.ClientInt, - replicaCount int, -) error { - monitor.Debug("Scaling database-operator") - return client.ScaleDeployment(namespace, "database-operator", replicaCount) -} - -func int32Ptr(i int32) *int32 { return &i } -func int64Ptr(i int64) *int64 { return &i } - -func toNameLabels(apiLabels *labels.API, operatorName string) *labels.Name { - return labels.MustForName(labels.MustForComponent(apiLabels, "operator"), operatorName) -} - -func getDatabaseOperatorNameLabels(apiLabels *labels.API) *labels.Name { - return toNameLabels(apiLabels, "database-operator") -} - -func EnsureDatabaseArtifacts( - monitor mntr.Monitor, - apiLabels *labels.API, - client kubernetes.ClientInt, - version string, - nodeselector map[string]string, - tolerations []core.Toleration, - customImageRegistry string, - gitops bool) error { - - monitor.WithFields(map[string]interface{}{ - "database": version, - }).Debug("Ensuring database artifacts") - - if version == "" { - return nil - } - - nameLabels := toNameLabels(apiLabels, "database-operator") - k8sNameLabels := labels.MustK8sMap(nameLabels) - - if err := client.ApplyServiceAccount(&core.ServiceAccount{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: k8sNameLabels, - }, - }); err != nil { - return err - } - - if err := client.ApplyClusterRole(&rbac.ClusterRole{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - Rules: []rbac.PolicyRule{{ - APIGroups: []string{"*"}, - Resources: []string{"*"}, - Verbs: []string{"*"}, - }}, - }); err != nil { - return err - } - - if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Labels: k8sNameLabels, - }, - - RoleRef: rbac.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: nameLabels.Name(), - }, - Subjects: []rbac.Subject{{ - Kind: "ServiceAccount", - Name: nameLabels.Name(), - Namespace: namespace, - }}, - }); err != nil { - return err - } - - if !gitops { - crd := `apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null - name: databases.caos.ch -spec: - group: caos.ch - names: - kind: Database - listKind: DatabaseList - plural: databases - singular: database - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - apiVersion: - description: Don't access X_ApiVersion, it is only exported for (de-)serialization. - Use Version and OverwriteVersion methods instead. - type: string - database: - type: object - kind: - type: string - spec: - properties: - customImageRegistry: - description: 'Use this registry to pull container images from - @default: ' - type: string - nodeSelector: - additionalProperties: - type: string - type: object - selfReconciling: - type: boolean - tolerations: - items: - description: The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . - properties: - effect: - description: Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string - type: object - type: array - verbose: - type: boolean - version: - type: string - required: - - selfReconciling - - verbose - type: object - version: - description: Don't access X_Version, it is only exported for (de-)serialization. - Use Version and OverwriteVersion methods instead. - type: string - required: - - database - - kind - - spec - type: object - status: - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: []` - - crdDefinition := &unstructured.Unstructured{} - if err := yaml.Unmarshal([]byte(crd), &crdDefinition.Object); err != nil { - return err - } - - if err := client.ApplyCRDResource( - crdDefinition, - ); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Database Operator crd ensured") - } - - var ( - cmd = []string{"/zitadelctl", "database", "--kubeconfig", ""} - volumes []core.Volume - volumeMounts []core.VolumeMount - ) - - if gitops { - cmd = append(cmd, "--gitops", "-f", "/secrets/orbconfig") - volumes = []core.Volume{{ - Name: "orbconfig", - VolumeSource: core.VolumeSource{ - Secret: &core.SecretVolumeSource{ - SecretName: "caos", - }, - }, - }} - volumeMounts = []core.VolumeMount{{ - Name: "orbconfig", - ReadOnly: true, - MountPath: "/secrets", - }} - } - - if _, _, analyticsEnabled := mntr.Environment(); !analyticsEnabled { - cmd = append(cmd, "--disable-analytics") - } - - deployment := &apps.Deployment{ - ObjectMeta: mach.ObjectMeta{ - Name: nameLabels.Name(), - Namespace: namespace, - Labels: k8sNameLabels, - }, - Spec: apps.DeploymentSpec{ - Replicas: int32Ptr(1), - Selector: &mach.LabelSelector{ - MatchLabels: labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)), - }, - Template: core.PodTemplateSpec{ - ObjectMeta: mach.ObjectMeta{ - Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), - }, - Spec: core.PodSpec{ - ServiceAccountName: nameLabels.Name(), - Containers: []core.Container{{ - Name: "database", - ImagePullPolicy: core.PullIfNotPresent, - Image: common.ZITADELOperatorImage.Reference(customImageRegistry, version), - Command: cmd, - Args: []string{}, - Ports: []core.ContainerPort{{ - Name: "metrics", - ContainerPort: 2112, - Protocol: "TCP", - }}, - VolumeMounts: volumeMounts, - Resources: core.ResourceRequirements{ - Limits: core.ResourceList{ - "cpu": resource.MustParse("500m"), - "memory": resource.MustParse("500Mi"), - }, - Requests: core.ResourceList{ - "cpu": resource.MustParse("250m"), - "memory": resource.MustParse("250Mi"), - }, - }, - }}, - NodeSelector: nodeselector, - Tolerations: tolerations, - Volumes: volumes, - TerminationGracePeriodSeconds: int64Ptr(10), - }, - }, - }, - } - - if err := client.ApplyDeployment(deployment, true); err != nil { - return err - } - monitor.WithFields(map[string]interface{}{ - "version": version, - }).Debug("Database Operator deployment ensured") - - return nil -} - -func DestroyDatabaseOperator( - monitor mntr.Monitor, - apiLabels *labels.API, - client kubernetes.ClientInt, - gitops bool, -) error { - nameLabels := getDatabaseOperatorNameLabels(apiLabels) - - monitor.WithFields(map[string]interface{}{}).Debug("Destroying database artifacts") - - if err := client.DeleteServiceAccount(namespace, nameLabels.Name()); err != nil { - return err - } - - if err := client.DeleteClusterRole(nameLabels.Name()); err != nil { - return err - } - - if err := client.DeleteClusterRoleBinding(nameLabels.Name()); err != nil { - return err - } - - if !gitops { - if err := client.DeleteCRDResource("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition", "databases.caos.ch"); err != nil { - return err - } - } - - if err := client.DeleteDeployment(namespace, nameLabels.Name()); err != nil { - return err - } - - return nil -} diff --git a/pkg/zitadel/migration.go b/pkg/zitadel/migration.go deleted file mode 100644 index 6749882905..0000000000 --- a/pkg/zitadel/migration.go +++ /dev/null @@ -1,67 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - orbconfig "github.com/caos/orbos/pkg/orb" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/zitadel" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" -) - -//Take care! to use this function you have to include migration files into the binary -func CrdMigrations( - monitor mntr.Monitor, - k8sClient *kubernetes.Client, - version *string, -) error { - desired, err := zitadel.ReadCrd(k8sClient) - if err != nil { - return err - } - - return migrations(monitor, nil, k8sClient, false, version, desired) -} - -//Take care! to use this function you have to include migration files into the binary -func GitOpsMigrations( - monitor mntr.Monitor, - orbCfg *orbconfig.Orb, - gitClient *git.Client, - k8sClient *kubernetes.Client, - version *string, -) error { - desired, err := gitClient.ReadTree(git.ZitadelFile) - if err != nil { - return err - } - - return migrations(monitor, orbCfg, k8sClient, true, version, desired) -} - -//Take care! to use this function you have to include migration files into the binary -func migrations( - monitor mntr.Monitor, - orbCfg *orbconfig.Orb, - k8sClient *kubernetes.Client, - gitops bool, - version *string, - desired *tree.Tree, -) error { - current := &tree.Tree{} - query, _, _, _, _, _, err := orb.AdaptFunc(orbCfg, "migration", version, gitops, []string{"migration"})(monitor, desired, current) - if err != nil { - return err - } - - ensure, err := query(k8sClient, map[string]interface{}{}) - if err != nil { - return err - } - - if err := ensure(k8sClient); err != nil { - return err - } - return nil -} diff --git a/pkg/zitadel/zitadel.go b/pkg/zitadel/zitadel.go deleted file mode 100644 index fc6c339849..0000000000 --- a/pkg/zitadel/zitadel.go +++ /dev/null @@ -1,65 +0,0 @@ -package zitadel - -import ( - "github.com/caos/orbos/mntr" - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes" - orbconfig "github.com/caos/orbos/pkg/orb" - "github.com/caos/orbos/pkg/tree" - "github.com/caos/zitadel/operator/api/zitadel" - "github.com/caos/zitadel/operator/zitadel/kinds/orb" -) - -func CrdScaleDown( - monitor mntr.Monitor, - k8sClient *kubernetes.Client, - version *string, -) error { - desired, err := zitadel.ReadCrd(k8sClient) - if err != nil { - return err - } - - return scaleDown(monitor, nil, k8sClient, false, version, desired) -} - -func GitOpsScaleDown( - monitor mntr.Monitor, - orbCfg *orbconfig.Orb, - gitClient *git.Client, - k8sClient *kubernetes.Client, - version *string, -) error { - desired, err := gitClient.ReadTree(git.ZitadelFile) - if err != nil { - return err - } - - return scaleDown(monitor, orbCfg, k8sClient, true, version, desired) -} - -//Take care! to use this function you have to include migration files into the binary -func scaleDown( - monitor mntr.Monitor, - orbCfg *orbconfig.Orb, - k8sClient *kubernetes.Client, - gitops bool, - version *string, - desired *tree.Tree, -) error { - current := &tree.Tree{} - query, _, _, _, _, _, err := orb.AdaptFunc(orbCfg, "scaledown", version, gitops, []string{"scaledown"})(monitor, desired, current) - if err != nil { - return err - } - - ensure, err := query(k8sClient, map[string]interface{}{}) - if err != nil { - return err - } - - if err := ensure(k8sClient); err != nil { - return err - } - return nil -} diff --git a/scripts/generateCrd.sh b/scripts/generateCrd.sh deleted file mode 100755 index f26561979c..0000000000 --- a/scripts/generateCrd.sh +++ /dev/null @@ -1,3 +0,0 @@ -controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./operator/..." - -controller-gen crd paths="./operator/..." output:crd:artifacts:config=test diff --git a/scripts/zitadelctl-debug.sh b/scripts/zitadelctl-debug.sh deleted file mode 100755 index f9093c3681..0000000000 --- a/scripts/zitadelctl-debug.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -set -e - -./build/operator/prebuild.sh "./migrations" - -dlv debug --api-version 2 --headless --listen 127.0.0.1:2345 --build-flags="-ldflags='$(./build/operator/ldflags.sh)'" ./cmd/zitadelctl -- "$@" diff --git a/scripts/zitadelctl.sh b/scripts/zitadelctl.sh deleted file mode 100755 index ff1d1cbc2d..0000000000 --- a/scripts/zitadelctl.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -set -e - -./build/operator/prebuild.sh "./migrations" -./build/operator/build.sh -exec ./zitadelctl "$@"