Repository: cnoe-io/idpbuilder Branch: main Commit: 50580da36900 Files: 186 Total size: 4.1 MB Directory structure: gitextract_a87kr30h/ ├── .devcontainer/ │ ├── devcontainer.json │ ├── postCreateCommand.sh │ └── postStartCommand.sh ├── .github/ │ ├── CODEOWNERS │ └── workflows/ │ ├── code-scanner.yaml │ ├── codespell.yaml │ ├── e2e.yaml │ ├── nightly.yaml │ ├── pr.yaml │ ├── release.yaml │ └── slash-commands.yaml ├── .gitignore ├── .goreleaser.yaml ├── .pre-commit-config.yaml ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── api/ │ └── v1alpha1/ │ ├── custom_package_types.go │ ├── gitrepository_types.go │ ├── groupversion_info.go │ ├── localbuild_types.go │ └── zz_generated.deepcopy.go ├── docs/ │ ├── images/ │ │ └── source/ │ │ └── idpbuilder.excalidraw │ ├── minimum-requirements.md │ ├── pluggable-packages.md │ └── private-registries.md ├── globals/ │ └── project.go ├── go.mod ├── go.sum ├── hack/ │ ├── argo-cd/ │ │ ├── argocd-application-controller.yaml │ │ ├── argocd-applicationset-controller.yaml │ │ ├── argocd-cm.yaml │ │ ├── argocd-rbac-dev.yaml │ │ ├── argocd-redis.yaml │ │ ├── argocd-repo-server.yaml │ │ ├── argocd-server.yaml │ │ ├── argocd-tls-certs-cm.yaml.tmpl │ │ ├── dex-server.yaml │ │ ├── generate-manifests.sh │ │ ├── ingress.yaml.tmpl │ │ ├── kustomization.yaml │ │ └── notifications-controller.yaml │ ├── boilerplate.go.txt │ ├── embedded-resources.sh │ ├── gitea/ │ │ ├── generate-manifests.sh │ │ ├── ingress.yaml.tmpl │ │ └── values.yaml │ ├── ingress-nginx/ │ │ ├── cm-ingress-nginx-controller.yaml │ │ ├── deployment-ingress-nginx.yaml │ │ ├── generate-manifests.sh │ │ ├── kustomization.yaml │ │ └── service-ingress-nginx.yaml.tmpl │ └── install.sh ├── main.go ├── pkg/ │ ├── build/ │ │ ├── build.go │ │ ├── build_test.go │ │ ├── coredns.go │ │ ├── templates/ │ │ │ └── coredns/ │ │ │ ├── cm-coredns-custom.yaml │ │ │ ├── cm-coredns-default.yaml.tmpl │ │ │ ├── cm-coredns.yaml │ │ │ └── deployment-coredns.yaml │ │ ├── tls.go │ │ └── tls_test.go │ ├── cmd/ │ │ ├── create/ │ │ │ ├── root.go │ │ │ └── root_test.go │ │ ├── delete/ │ │ │ └── root.go │ │ ├── get/ │ │ │ ├── clusters.go │ │ │ ├── packages.go │ │ │ ├── root.go │ │ │ ├── secrets.go │ │ │ └── secrets_test.go │ │ ├── helpers/ │ │ │ ├── logger.go │ │ │ ├── test-data/ │ │ │ │ ├── notk8s.yaml │ │ │ │ ├── notyaml.yaml │ │ │ │ └── valid.yaml │ │ │ ├── validation.go │ │ │ └── validation_test.go │ │ ├── root.go │ │ └── version/ │ │ └── root.go │ ├── controllers/ │ │ ├── crd.go │ │ ├── custompackage/ │ │ │ ├── controller.go │ │ │ ├── controller_test.go │ │ │ └── test/ │ │ │ └── resources/ │ │ │ └── customPackages/ │ │ │ ├── applicationSet/ │ │ │ │ ├── generator-matrix.yaml │ │ │ │ ├── generator-multi-sources.yaml │ │ │ │ ├── generator-single-source.yaml │ │ │ │ ├── no-generator-single-source.yaml │ │ │ │ └── test1/ │ │ │ │ └── apps/ │ │ │ │ ├── guestbook/ │ │ │ │ │ ├── guestbook-ui-deployment.yaml │ │ │ │ │ ├── guestbook-ui-svc.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── guestbook2/ │ │ │ │ ├── guestbook-ui-deployment.yaml │ │ │ │ ├── guestbook-ui-svc.yaml │ │ │ │ └── kustomization.yaml │ │ │ ├── helm/ │ │ │ │ ├── app.yaml │ │ │ │ └── test/ │ │ │ │ ├── Chart.yaml │ │ │ │ ├── templates/ │ │ │ │ │ └── cm.yaml │ │ │ │ └── values.yaml │ │ │ ├── testDir/ │ │ │ │ ├── app.yaml │ │ │ │ ├── app1/ │ │ │ │ │ └── cm.yaml │ │ │ │ ├── app2/ │ │ │ │ │ ├── one/ │ │ │ │ │ │ └── cm.yaml │ │ │ │ │ └── two/ │ │ │ │ │ └── cm.yaml │ │ │ │ └── app2.yaml │ │ │ └── testDir2/ │ │ │ ├── exampleApp.yaml │ │ │ └── exampleApp2.yaml │ │ ├── doc.go │ │ ├── gitrepository/ │ │ │ ├── controller.go │ │ │ ├── controller_test.go │ │ │ ├── git_repository.go │ │ │ ├── gitea.go │ │ │ ├── github.go │ │ │ ├── github_test.go │ │ │ └── test/ │ │ │ └── resources/ │ │ │ └── file1 │ │ ├── localbuild/ │ │ │ ├── argo.go │ │ │ ├── argo_test.go │ │ │ ├── controller.go │ │ │ ├── gitea.go │ │ │ ├── gitea_test.go │ │ │ ├── installer.go │ │ │ ├── nginx.go │ │ │ └── resources/ │ │ │ ├── argo/ │ │ │ │ ├── ingress.yaml │ │ │ │ └── install.yaml │ │ │ ├── gitea/ │ │ │ │ └── k8s/ │ │ │ │ └── install.yaml │ │ │ └── nginx/ │ │ │ └── k8s/ │ │ │ └── ingress-nginx.yaml │ │ ├── resources/ │ │ │ ├── idpbuilder.cnoe.io_custompackages.yaml │ │ │ ├── idpbuilder.cnoe.io_gitrepositories.yaml │ │ │ └── idpbuilder.cnoe.io_localbuilds.yaml │ │ └── run.go │ ├── k8s/ │ │ ├── client.go │ │ ├── deserialize.go │ │ ├── deserialize_test.go │ │ ├── schema.go │ │ ├── test-resources/ │ │ │ ├── input/ │ │ │ │ ├── argocd/ │ │ │ │ │ └── install.yaml │ │ │ │ ├── argocd-cm.yaml │ │ │ │ ├── extra.yaml │ │ │ │ ├── extra.yaml.tmpl │ │ │ │ └── nginx/ │ │ │ │ └── install.yaml │ │ │ └── output/ │ │ │ ├── argocd/ │ │ │ │ └── install.yaml │ │ │ └── nginx/ │ │ │ ├── install-tmpl.yaml │ │ │ └── install.yaml │ │ ├── util.go │ │ └── util_test.go │ ├── kind/ │ │ ├── cluster.go │ │ ├── cluster_test.go │ │ ├── config.go │ │ ├── config_integration_test.go │ │ ├── config_test.go │ │ ├── kindlogger.go │ │ ├── resources/ │ │ │ ├── hosts-mirror.toml.tmpl │ │ │ ├── hosts.toml.tmpl │ │ │ └── kind.yaml.tmpl │ │ └── testdata/ │ │ ├── custom-kind.yaml.tmpl │ │ ├── empty.json │ │ ├── expected/ │ │ │ ├── label-only.yaml │ │ │ ├── no-port-multi.yaml │ │ │ ├── no-port.yaml │ │ │ └── port-only.yaml │ │ ├── label-only.yaml │ │ ├── no-node.yaml │ │ ├── no-port-multi.yaml │ │ ├── no-port.yaml │ │ └── port-only.yaml │ ├── logger/ │ │ └── handler.go │ ├── printer/ │ │ ├── cluster.go │ │ ├── package.go │ │ ├── printer.go │ │ ├── secret.go │ │ └── types/ │ │ └── internal_types.go │ ├── resources/ │ │ └── localbuild/ │ │ └── application.go │ └── util/ │ ├── argocd.go │ ├── files/ │ │ └── files.go │ ├── fs/ │ │ ├── fs.go │ │ └── fs_test.go │ ├── git_repository.go │ ├── git_repository_test.go │ ├── gitea.go │ ├── gitea_test.go │ ├── idp.go │ ├── k8s.go │ ├── secret.go │ ├── url.go │ ├── url_test.go │ ├── util.go │ └── util_test.go └── tests/ └── e2e/ ├── docker/ │ ├── docker_test.go │ └── test-dockerfile └── e2e.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .devcontainer/devcontainer.json ================================================ { "image": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu", "features": { "ghcr.io/devcontainers/features/go:1": { "version": "1.26" }, "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, "postCreateCommand": ".devcontainer/postCreateCommand.sh", "postStartCommand": ".devcontainer/postStartCommand.sh", "workspaceFolder": "/home/vscode/idpbuilder", "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/idpbuilder,type=bind", "hostRequirements": { "cpus": 4 }, "remoteEnv": { "PATH": "${containerEnv:PATH}:/home/vscode/idpbuilder" } } ================================================ FILE: .devcontainer/postCreateCommand.sh ================================================ #!/usr/bin/env bash # For Kubectl AMD64 / x86_64 [ $(uname -m) = x86_64 ] && curl -sLO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" # For Kubectl ARM64 [ $(uname -m) = aarch64 ] && curl -sLO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl" chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl # For Kind AMD64 / x86_64 [ $(uname -m) = x86_64 ] && curl -sLo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64 # For Kind ARM64 [ $(uname -m) = aarch64 ] && curl -sLo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-arm64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind # setup autocomplete for kubectl and alias k sudo apt-get update -y && sudo apt-get install bash-completion -y mkdir $HOME/.kube echo "source <(kubectl completion bash)" >> $HOME/.bashrc echo "alias k=kubectl" >> $HOME/.bashrc echo "complete -F __start_kubectl k" >> $HOME/.bashrc # Configure git if environment variables are set if [ -n "$GIT_COMMITER_NAME" ]; then echo "Configuring git user.name to: $GIT_COMMITER_NAME" git config --global user.name "$GIT_COMMITER_NAME" fi if [ -n "$GIT_COMMITER_EMAIL" ]; then echo "Configuring git user.email to: $GIT_COMMITER_EMAIL" git config --global user.email "$GIT_COMMITER_EMAIL" fi # 1. Configure GPG agent mkdir -p ~/.gnupg echo "pinentry-program /usr/bin/pinentry" > ~/.gnupg/gpg-agent.conf echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf # 2. Configure GPG client echo "use-agent" > ~/.gnupg/gpg.conf echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf # 3. Restart GPG agent and set environment gpgconf --kill gpg-agent export GPG_TTY=$(tty) echo 'export GPG_TTY=$(tty)' >> ~/.bashrc # 4. Configure Git for GPG signing git config --global commit.gpgsign true git config --global tag.gpgsign true git config --global gpg.program gpg ================================================ FILE: .devcontainer/postStartCommand.sh ================================================ #!/bin/bash # Import GPG key if both parts are available if [ -n "$GPG_SECRET_KEY_PART1" ] && [ -n "$GPG_SECRET_KEY_PART2" ]; then echo "Importing GPG key..." echo "$GPG_SECRET_KEY_PART1$GPG_SECRET_KEY_PART2" | tr -d "'" | base64 -d | gunzip | gpg --batch --yes --no-tty --import if [ $? -eq 0 ]; then echo "GPG key imported successfully" # Automatically configure Git to use the imported key for signing echo "Configuring Git to use the imported GPG key..." GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep -E "^sec" | head -1 | awk '{print $2}' | cut -d'/' -f2) if [ -n "$GPG_KEY_ID" ]; then git config --global user.signingkey "$GPG_KEY_ID" echo "Git configured to use GPG key: $GPG_KEY_ID" else echo "Warning: Could not detect GPG key ID for Git configuration" fi else echo "Failed to import GPG key" fi else echo "GPG key parts not found, skipping GPG import" fi ================================================ FILE: .github/CODEOWNERS ================================================ # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Any committer can add themselves to any of the path patterns # and will subsequently get requested as a reviewer for any PRs # that change matching files. /* @cnoe-io/idpbuilder-approvers /* @cnoe-io/idpbuilder-admin ================================================ FILE: .github/workflows/code-scanner.yaml ================================================ name: code-scanner on: push: branches: [ "main" ] pull_request: # The branches below must be a subset of the branches above branches: [ "main" ] types: [opened, ready_for_review, synchronize] permissions: contents: write security-events: write # for github/codeql-action/upload-sarif to upload SARIF results jobs: code-analysis: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6 - run: ls -al - name: Scan current project id: scan uses: anchore/scan-action@v7 with: fail-build: false path: "." - name: Upload scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: ${{ steps.scan.outputs.sarif }} ================================================ FILE: .github/workflows/codespell.yaml ================================================ --- name: Codespell on: push: branches: [main] pull_request: branches: [main] permissions: contents: read jobs: codespell: name: Check for spelling errors runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - name: Codespell uses: codespell-project/actions-codespell@v2 with: check_filenames: true # When using this Action in other repos, the --skip option below can be removed skip: "*.excalidraw,*.git,*.png,*.jpg,*.svg,go.mod,go.sum,./pkg/controllers/localbuild/resources" continue-on-error: true # The PR checks will not fail, but the possible spelling issues will still be reported for review and correction ================================================ FILE: .github/workflows/e2e.yaml ================================================ name: E2E on: push: branches: - 'main' paths: - '**.go' - 'go.sum' - 'go.mod' repository_dispatch: types: [e2e-command] jobs: e2e: runs-on: ubuntu-22.04 if: ${{ github.event.ref != '' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: '1.26' - name: Run tests run: | make e2e # invoked by slash command workflow e2e-slash-command: runs-on: ubuntu-22.04 if: ${{ github.event.action == 'e2e-command' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: ${{ github.event.client_payload.pull_request.head.repo.full_name }} ref: ${{ github.event.client_payload.pull_request.head.ref }} fetch-depth: 0 - name: Setup Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: '1.26' - name: Run tests run: | make e2e ================================================ FILE: .github/workflows/nightly.yaml ================================================ name: nightly on: # This can be used to automatically publish nightlies at UTC nighttime schedule: - cron: '0 7 * * *' # run at 7 AM UTC # This can be used to allow manually triggering nightlies from the web interface workflow_dispatch: jobs: nightly: runs-on: ubuntu-22.04 steps: - name: Generate a token id: generate-token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.CNOE_GH_WORKFLOW_TOKEN_APP_ID }} private-key: ${{ secrets.CNOE_GH_WORKFLOW_TOKEN_PRIVATE_KEY }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: token: ${{ steps.generate-token.outputs.token }} fetch-depth: 0 - run: git fetch --force --tags - name: 'Push new tag' run: | git config user.name "${GITHUB_ACTOR}" git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" # A previous release was created using a lightweight tag # git describe by default includes only annotated tags # git describe --tags includes lightweight tags as well DESCRIBE=`git tag -l --sort=-v:refname | grep -v nightly | head -n 1` MAJOR_VERSION=`echo $DESCRIBE | awk '{split($0,a,"."); print a[1]}'` MINOR_VERSION=`echo $DESCRIBE | awk '{split($0,a,"."); print a[2]}'` MINOR_VERSION="$((${MINOR_VERSION} + 1))" TAG="${MAJOR_VERSION}.${MINOR_VERSION}.0-nightly.$(date +'%Y%m%d')" git tag -a $TAG -m "$TAG: nightly build" git push origin $TAG - name: Find previous nightly run: | prev_tag=$(git tag | grep "nightly" | sort -r --version-sort | head -n 2 | tail -n 1) echo "PREVIOUS_NIGHTLY_TAG=$prev_tag" >> $GITHUB_ENV git push --delete origin $prev_tag - name: 'Clean up nightly releases' uses: actions/github-script@v8 with: github-token: ${{ steps.generate-token.outputs.token }} script: | const latestRelease = await github.rest.repos.getReleaseByTag({ owner: "${{ github.repository_owner }}", repo: "${{ github.event.repository.name }}", tag: "${{ env.PREVIOUS_NIGHTLY_TAG }}" }); console.log(`Release ${latestRelease}`); if (latestRelease && latestRelease.data && latestRelease.data.id) { await github.rest.repos.deleteRelease({ owner: "${{ github.repository_owner }}", repo: "${{ github.event.repository.name }}", release_id: latestRelease.data.id, }); console.log(`Release id ${latestRelease.data.id} has been deleted.`); } else { console.log("No latest release found or failed to retrieve it."); } ================================================ FILE: .github/workflows/pr.yaml ================================================ name: PR on: pull_request: types: [opened, ready_for_review, synchronize] jobs: build: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: '1.26' - name: Run tests run: | make build if [[ -n $(git status --porcelain) ]]; then echo "git is in dirty state"; git status --porcelain=2 --branch exit 1 fi make test ================================================ FILE: .github/workflows/release.yaml ================================================ name: release on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+-nightly.[0-9]+' permissions: contents: write jobs: release: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - run: git fetch --force --tags - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: '1.26' - name: Set GORELEASER_PREVIOUS_TAG in actual release if: ${{ !contains(github.ref, '-nightly') }} # find previous tag by filtering out nightly tags and choosing the # second to last tag (last one is the current release) run: | prev_tag=$(git tag | grep -v "nightly" | sort -r --version-sort | head -n 2 | tail -n 1) echo "GORELEASER_PREVIOUS_TAG=$prev_tag" >> $GITHUB_ENV # Ensure generation tools run - name: build run: | OUT_FILE=/tmp/idpbuilder make build - name: Generate a homebrew tap update token id: generate-token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.CNOE_HOMEBREW_APP_ID }} private-key: ${{ secrets.CNOE_HOMEBREW_PRIVATE_KEY }} repositories: | homebrew-tap - name: GoReleaser uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 id: run-goreleaser with: version: latest args: release --clean --timeout 30m env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HOMEBREW_TOKEN: ${{ steps.generate-token.outputs.token }} GORELEASER_CURRENT_TAG: ${{ github.ref_name }} ================================================ FILE: .github/workflows/slash-commands.yaml ================================================ name: slash-commands on: issue_comment: types: [created] jobs: slash_command_dispatch: runs-on: ubuntu-22.04 steps: - name: Generate a token id: generate-token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.CNOE_GH_WORKFLOW_TOKEN_APP_ID }} private-key: ${{ secrets.CNOE_GH_WORKFLOW_TOKEN_PRIVATE_KEY }} - name: Slash Command Dispatch uses: peter-evans/slash-command-dispatch@v5 with: token: ${{ steps.generate-token.outputs.token }} commands: | e2e permission: write issue-type: pull-request ================================================ FILE: .gitignore ================================================ idpbuilder bin/* .DS_Store cover.out __debug* .vscode .idea ================================================ FILE: .goreleaser.yaml ================================================ version: 2 project_name: idpbuilder before: hooks: - go mod tidy release: # Mark nightly build as prerelease based on tag prerelease: auto builds: - env: - CGO_ENABLED=0 goos: - linux - darwin goarch: - amd64 - arm64 ldflags: - -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.idpbuilderVersion={{ .Version }} - -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.gitCommit={{ .FullCommit }} - -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.buildDate={{ .CommitDate }} - -w - -s binary: idpbuilder ignore: - goos: linux goarch: '386' brews: # For non version installations - name: "idpbuilder" homepage: "https://cnoe.io" skip_upload: "{{ contains .Tag \"nightly\" }}" # Don't upload this formula if the build is nightly repository: owner: cnoe-io name: homebrew-tap token: "{{ .Env.HOMEBREW_TOKEN }}" commit_author: name: "CNOEAutomation" email: "noreply@cnoe.io" directory: Formula install: | bin.install "idpbuilder" test: | system "#{bin}/idpbuilder version" # For versioned and nightly installations - name: "{{ if contains .Tag \"nightly\" }}idpbuilder-nightly{{ else }}idpbuilder@{{ .Major }}.{{ .Minor }}.{{ .Patch }}{{ end }}" homepage: "https://cnoe.io" repository: owner: cnoe-io name: homebrew-tap token: "{{ .Env.HOMEBREW_TOKEN }}" commit_author: name: "CNOEAutomation" email: "noreply@cnoe.io" directory: Formula install: | bin.install "idpbuilder" test: | system "#{bin}/idpbuilder version" archives: - format: tar.gz name_template: >- {{ .ProjectName }}-{{ .Os }}-{{ .Arch }} checksum: name_template: 'checksums.txt' snapshot: version_template: "{{ incpatch .Version }}-next" changelog: sort: asc filters: exclude: - '^docs:' - '^test:' use: github format: "{{.SHA}}: {{.Message}} [{{.AuthorName}}](@{{.AuthorUsername}})" groups: - title: "✨ Features" regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$' order: 0 - title: "🐛 Bug fixes" regexp: '^.*?(fix|bug)(\([[:word:]]+\))??!?:.+$' order: 1 - title: "🔧 Others" order: 999 ================================================ FILE: .pre-commit-config.yaml ================================================ # For more information, visit: https://pre-commit.com # To run locally: # 1. Install pre-commit: pip install pre-commit # 2. Run pre-commit checks on all files: pre-commit run --all-files repos: - repo: https://github.com/codespell-project/codespell rev: v2.2.6 hooks: - id: codespell args: ["--skip=*.excalidraw,*.git,*.png,*.jpg,*.svg,go.sum,go.mod,./pkg/controllers/localbuild/resources"] ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing guide Welcome to the project, and thanks for considering contributing to this project. If you have any questions or need clarifications on topics covered here, please feel free to reach out to us on the [#cnoe-interest](https://cloud-native.slack.com/archives/C05TN9WFN5S) channel on CNCF Slack. ## Setting up a development environment To get started with the project on your machine, you need to install the following tools: 1. Go 1.21+. See [this official guide](https://go.dev/doc/install) from Go authors. 2. Make. You can install it through a package manager on your system. E.g. Install `build-essential` for Ubuntu systems. 3. Docker. Similar to Make, you can install it through your package manager or [Docker Desktop](https://www.docker.com/products/docker-desktop/). Once required tools are installed, clone this repository. `git clone https://github.com/cnoe-io/idpbuilder.git`. Then change your current working directory to the repository root. e.g. `cd idpbuilder`. All subsequent commands described in this document assumes they are executed from the repository root. Ensure your docker daemon is running and available. e.g. `docker images` command should not error out. ## Building from the main branch 1. Checkout the main branch. `git checkout main` 2. Build the binary. `make build`. This compiles the project. It will take several minutes for the first time. Example output shown below: ``` ~/idpbuilder$ make build test -s /home/ubuntu/idpbuilder/bin/controller-gen && /home/ubuntu/idpbuilder/bin/controller-gen --version | grep -q v0.12.0 || \ GOBIN=/home/ubuntu/idpbuilder/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.12.0 /home/ubuntu/idpbuilder/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./api/..." output:crd:artifacts:config=pkg/controllers/resources /home/ubuntu/idpbuilder/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..." go fmt ./... go vet ./... go build -o idpbuilder main.go ``` 3. Once build finishes, you should have an executable file called `idpbuilder` in the root of the repository. 4. The file is ready to use. Execute this command to confirm: `./idpbuilder --help` ### Testing basic functionalities To test the very basic functionality of idpbuilder, Run the following command: `./idpbuilder create` This command creates a kind cluster, expose associated endpoints to your local machine using an ingress controller and deploy the following packages: 1. [Kind](https://kind.sigs.k8s.io/) cluster. 2. [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) resources. 3. [Gitea](https://about.gitea.com/) resources. 4. [Backstage](https://backstage.io/) resources. They are deployed as ArgoCD Applications with the Gitea repositories set as their sources. UIs for Backstage, Gitea, and ArgoCD are accessible on the machine: * Gitea: https://gitea.cnoe.localtest.me:8443/explore/repos * Backstage: https://backstage.cnoe.localtest.me:8443/ * ArgoCD: https://argocd.cnoe.localtest.me:8443/applications #### Getting credentials for packages Credentials for core packages can be obtained with: ```bash idpbuilder get secrets ``` As described in the main readme file, the above command is equivalent to running: ```bash kubectl -n argocd get secret argocd-initial-admin-secret kubectl get secrets -n gitea gitea-admin-secret kubectl get secrets -A -l cnoe.io/cli-secret=true ``` All ArgoCD applications should be synced and healthy. You can check them in the UI or ``` kubectl get application -n argocd ``` ### Upgrading a core component The process to upgrade a core component: Argo CD, Gitea, Ingress is not so complex but requires to take care about the following points: - Select the core component to be upgraded and get its current version. See the kustomization file under the `hack/` folder and the resource YAML file of the resources to be installed - Create a ticket describing the new sibling version of the core component to be bumped - Bump the version part of the kustomization file. Example for argocd: https://github.com/cnoe-io/idpbuilder/blob/main/hack/argo-cd/kustomization.yaml#L4 - Review the patched files to see if changes are needed (new file(s), files to be deleted or files to be changed). Example for argocd: https://github.com/cnoe-io/idpbuilder/blob/main/hack/argo-cd/kustomization.yaml#L7-L16 - Generate the new resources YAML files using the bash script: `generate-manifests.sh` - Build a new idpbuilder binary - Test it locally like also using the e2e integration test: `make e2e` - Review the test cases if changes are needed too - Update the documentation to detail which version of the core component has been bumped like also for which version (or range of versions) of idpbuilder the new version of the component apply for. **NOTES**: - For some components, it could be possible that you also have to upgrade the version of the go library within the `go.mod` file. Example for gitea: `code.gitea.io/sdk/gitea v0.16.0` - For Argo CD, we use a separate GitHub project (till a better solution is implemented) packaging a subset of the Argo CD API. Review carefully this file please: https://github.com/cnoe-io/argocd-api?tab=readme-ov-file#read-this-first ## Preparing a Pull Request This repository requires a [Developer Certificate of Origin (DCO)](https://developercertificate.org/) signature. When preparing to send in a pull request, please make sure your commit is signed. You can achieve this by doing a `git commit --sign` or `git commit -s` when making the commit. ## Project Information ### Default manifests installed by idpbuilder The default manifests for the core packages are available [here](pkg/controllers/localbuild/resources). These are generated by scripts. If you want to make changes to them, see below. #### ArgoCD ArgoCD manifests are generated using a bash script available [here](./hack/argo-cd/generate-manifests.sh). This script runs kustomize to modify the basic installation manifests provided by ArgoCD. Modifications include: 1. Prevent notification and dex pods from running. This is done to keep the number of pods running low by default. 2. Use the annotation tracking instead of the default label tracking. Annotation tracking allows you to avoid [problems caused by the label tracking method](https://argo-cd.readthedocs.io/en/stable/user-guide/resource_tracking/). In addition, this configuration is required when using Crossplane. 3. Support for path based routing. #### Gitea Gitea manifests are generated using a bash script available [here](./hack/gitea/generate-manifests.sh). This script runs helm template to generate most files. See the values file for more information. #### Ingress-nginx ingress-nginx manifests are generated using a bash script available [here](./hack/ingress-nginx/generate-manifests.sh). This script runs kustomize to modify the basic installation manifests provided by ingress-nginx. ## Architecture idpbuilder is made of two phases: CLI and Kubernetes controllers. ![idpbuilder.png](docs/images/idpbuilder.png) ### CLI When the idpbuilder binary is executed, it starts with the CLI phase. 1. This is the phase where command flags are parsed and translated into relevant Go structs' fields. Most notably the [`LocalBuild`](https://github.com/cnoe-io/idpbuilder/blob/main/api/v1alpha1/localbuild_types.go) struct. 2. Create a Kind cluster, then update the kubeconfig file. 3. Once the kind cluster is started and relevant fields are populated, Kubernetes controllers are started: * `LocalbuildReconciler` responsible for bootstrapping the cluster with absolute necessary packages. Creates Custom Resources (CRs) and installs embedded manifests. * `RepositoryReconciler` responsible for creating and managing Gitea repository and repository contents. * `CustomPackageReconciler` responsible for managing custom packages. 4. They are all managed by a single Kubernetes controller manager. 5. Once controllers are started, CRs corresponding to these controllers are created. For example for Backstage, it creates a GitRepository CR and ArgoCD Application. 6. CLI then waits for these CRs to be ready. ### Controllers During this phase, controllers act on CRs created by the CLI phase. Resources such as Gitea repositories and ArgoCD applications are created. #### LocalbuildReconciler `LocalbuildReconciler` bootstraps the cluster using embedded manifests. Embedded manifests are yaml files that are baked into the binary at compile time. 1. Install core packages. They are essential services that are needed for the user experiences we want to enable: * Gitea. This is the in-cluster Git server that hosts Git repositories. * Ingress-nginx. This is necessary to expose services inside the cluster to the users. * ArgoCD. This is used as the packaging mechanism. Its primary purpose is to deploy manifests from gitea repositories. 2. Once they are installed, it creates `GitRepository` CRs for core packages. This CR represents the git repository on the Gitea server. 3. Create ArgoCD applications for the apps. Point them to the Gitea repositories. From here on, ArgoCD manages the core packages. Once core packages are installed, it creates the other embedded applications: Backstage and Crossplane. 1. Create `GitRepository` CRs for the apps. 2. Create ArgoCD applications for the apps. Point them to the Gitea repositories. #### RepositoryReconciler `RepositoryReconciler` creates Gitea repositories. The content of the repositories can either be sourced from Embedded file system or local file system. #### CustomPackageReconciler `CustomPackageReconciler` parses the specified ArgoCD application files. If they specify repository URL with the scheme `cnoe://`, it creates `GitRepository` CR with source specified as local, then creates ArgoCD application with the repository URL replaced. For example, if an ArgoCD application is specified as the following. ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application spec: source: repoURL: cnoe://busybox ``` Then, the actual object created is this. ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application spec: source: repoURL: http://my-gitea-http.gitea.svc.cluster.local:3000/giteaAdmin/idpbuilder-localdev-my-app-busybox.git ``` ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2023] Autodesk 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. ================================================ FILE: Makefile ================================================ LD_FLAGS=-ldflags " \ -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.idpbuilderVersion=$(shell git describe --always --tags --dirty --broken) \ -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.gitCommit=$(shell git rev-parse HEAD) \ -X github.com/cnoe-io/idpbuilder/pkg/cmd/version.buildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \ " # The name of the binary. Defaults to idpbuilder OUT_FILE ?= idpbuilder .PHONY: build build: manifests generate fmt vet embedded-resources go build $(LD_FLAGS) -o $(OUT_FILE) main.go # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION = 1.29.1 ## Location to install dependencies to LOCALBIN ?= $(shell pwd)/bin $(LOCALBIN): mkdir -p $(LOCALBIN) CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen ENVTEST ?= $(LOCALBIN)/setup-envtest KUSTOMIZE ?= $(LOCALBIN)/kustomize HELM_TGZ ?= $(LOCALBIN)/helm.tar.gz HELM ?= $(LOCALBIN)/helm ## Tool Versions CONTROLLER_TOOLS_VERSION ?= v0.20.0 .PHONY: fmt fmt: ## Run go fmt against code. go fmt ./... .PHONY: vet vet: ## Run go vet against code. go vet ./... .PHONY: test test: manifests generate fmt vet envtest ## Run tests. ifeq ($(RUN),) KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -p 1 --tags=integration ./... -coverprofile cover.out else KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -p 1 --tags=integration ./... -coverprofile cover.out -run $(RUN) endif .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..." .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./api/..." output:crd:artifacts:config=pkg/controllers/resources .PHONY: controller-gen controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. $(CONTROLLER_GEN): $(LOCALBIN) test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) .PHONY: kustomize kustomize: ## Download kustomize if necessary ifeq (,$(wildcard $(KUSTOMIZE))) cd $(LOCALBIN) && curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash endif helm_os := $(shell uname | tr '[:upper:]' '[:lower:]') helm_version ?= 3.15.0 ifeq ($(shell uname -m), x86_64) helm_arch ?= amd64 endif ifeq ($(shell uname -m), arm64) helm_arch ?= arm64 endif ifeq ($(shell uname -m), aarch64) helm_arch ?= arm64 endif .PHONY: helm helm: ## Download helm if necessary ifeq (,$(wildcard $(HELM))) curl https://get.helm.sh/helm-v$(helm_version)-$(helm_os)-$(helm_arch).tar.gz -o $(HELM_TGZ) tar xvzf $(HELM_TGZ) -C $(LOCALBIN) --strip-components 1 $(helm_os)-$(helm_arch)/helm chmod +x $(HELM) endif .PHONY: envtest envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest .PHONY: embedded-resources embedded-resources: kustomize helm export PATH=$(LOCALBIN):$$PATH; ./hack/embedded-resources.sh; .PHONY: e2e e2e: build go test -v -p 1 -timeout 15m --tags=e2e ./tests/e2e/... ================================================ FILE: README.md ================================================ [![Codespell][codespell-badge]][codespell-link] [![E2E][e2e-badge]][e2e-link] [![Go Report Card][report-badge]][report-link] [![Commit Activity][commit-activity-badge]][commit-activity-link] # IDP Builder Internal development platform binary launcher. ## About Spin up a complete internal developer platform using industry standard technologies like Kubernetes, Argo, and backstage with only Docker required as a dependency. This can be useful in several ways: * Create a single binary which can demonstrate an IDP reference implementation. * Use within CI to perform integration testing. * Use as a local development environment for platform engineers. ## Installation ### Using [Homebrew](https://brew.sh) + Stable Version ```bash brew install cnoe-io/tap/idpbuilder ``` + Specific Stable Version ```bash brew install cnoe-io/tap/idpbuilder@ ``` + Nightly Version ```bash brew install cnoe-io/tap/idpbuilder-nightly ``` ### From Releases Another way to get started is to grab the idpbuilder binary for your platform and run it. You can visit our [releases](https://github.com/cnoe-io/idpbuilder/releases) page to download the version for your system, or run the following commands: ```bash arch=$(if [[ "$(uname -m)" == "x86_64" ]]; then echo "amd64"; else uname -m; fi) os=$(uname -s | tr '[:upper:]' '[:lower:]') idpbuilder_latest_tag=$(curl --silent "https://api.github.com/repos/cnoe-io/idpbuilder/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') curl -LO https://github.com/cnoe-io/idpbuilder/releases/download/$idpbuilder_latest_tag/idpbuilder-$os-$arch.tar.gz tar xvzf idpbuilder-$os-$arch.tar.gz ``` Download latest extract idpbuilder binary ```bash cd ~/bin curl -vskL -O https://github.com/cnoe-io/idpbuilder/releases/latest/download/idpbuilder-linux-amd64.tar.gz tar xvzf idpbuilder-linux-amd64.tar.gz idpbuilder ``` ## Getting Started You can then run idpbuilder with the create argument to spin up your CNOE IDP: ```bash ./idpbuilder create ``` For more detailed information, checkout our [documentation](https://cnoe.io/docs/idpbuilder) on getting started with idpbuilder. ## Community - If you have questions or concerns about this tool, please feel free to reach out to us on the [CNCF Slack Channel](https://cloud-native.slack.com/archives/C05TN9WFN5S). - You can also join our community meetings to meet the team and ask any questions. Checkout [this calendar](https://calendar.google.com/calendar/embed?src=064a2adfce866ccb02e61663a09f99147f22f06374e7a8994066bdc81e066986%40group.calendar.google.com&ctz=America%2FLos_Angeles) for more information. ## Contribution Checkout the [contribution doc](./CONTRIBUTING.md) for contribution guidelines and more information on how to set up your local environment. [codespell-badge]: https://github.com/cnoe-io/idpbuilder/actions/workflows/codespell.yaml/badge.svg [codespell-link]: https://github.com/cnoe-io/idpbuilder/actions/workflows/codespell.yaml [e2e-badge]: https://github.com/cnoe-io/idpbuilder/actions/workflows/e2e.yaml/badge.svg [e2e-link]: https://github.com/cnoe-io/idpbuilder/actions/workflows/e2e.yaml [report-badge]: https://goreportcard.com/badge/github.com/cnoe-io/idpbuilder [report-link]: https://goreportcard.com/report/github.com/cnoe-io/idpbuilder [commit-activity-badge]: https://img.shields.io/github/commit-activity/m/cnoe-io/idpbuilder [commit-activity-link]: https://github.com/cnoe-io/idpbuilder/pulse ================================================ FILE: api/v1alpha1/custom_package_types.go ================================================ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( CNOEURIScheme = "cnoe://" ) // +kubebuilder:object:root=true // +kubebuilder:subresource:status type CustomPackage struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec CustomPackageSpec `json:"spec,omitempty"` Status CustomPackageStatus `json:"status,omitempty"` } // +kubebuilder:object:root=true type CustomPackageList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []CustomPackage `json:"items"` } // CustomPackageSpec controls the installation of the custom applications. type CustomPackageSpec struct { ArgoCD ArgoCDPackageSpec `json:"argoCD,omitempty"` // GitServerURL specifies the base URL for the git server for API calls. // for example, https://gitea.cnoe.localtest.me:8443 GitServerURL string `json:"gitServerURL"` GitServerAuthSecretRef SecretReference `json:"gitServerAuthSecretRef"` // InternalGitServeURL specifies the base URL for the git server accessible within the cluster. // for example, http://my-gitea-http.gitea.svc.cluster.local:3000 InternalGitServeURL string `json:"internalGitServeURL"` RemoteRepository RemoteRepositorySpec `json:"remoteRepository"` // Replicate specifies whether to replicate remote or local contents to the local gitea server. // +kubebuilder:default:=false Replicate bool `json:"replicate"` } // RemoteRepositorySpec specifies information about remote repositories. type RemoteRepositorySpec struct { CloneSubmodules bool `json:"cloneSubmodules"` Path string `json:"path"` // Url specifies the url to the repository containing the ArgoCD application file Url string `json:"url"` // Ref specifies the specific ref supported by git fetch Ref string `json:"ref"` } type ArgoCDPackageSpec struct { // ApplicationFile specifies the absolute path to the ArgoCD application file ApplicationFile string `json:"applicationFile"` Name string `json:"name"` Namespace string `json:"namespace"` // +kubebuilder:validation:Enum:=Application;ApplicationSet Type string `json:"type"` } type CustomPackageStatus struct { // A Custom package is considered synced when the in-cluster repository url is set as the repository URL // This only applies for a package that references local directories Synced bool `json:"synced,omitempty"` GitRepositoryRefs []ObjectRef `json:"gitRepositoryRefs,omitempty"` } type ObjectRef struct { APIVersion string `json:"apiVersion,omitempty"` Name string `json:"name,omitempty"` Namespace string `json:"namespace,omitempty"` Kind string `json:"kind,omitempty"` UID string `json:"uid,omitempty"` } ================================================ FILE: api/v1alpha1/gitrepository_types.go ================================================ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( GitProviderGitea = "gitea" GitProviderGitHub = "github" GiteaAdminUserName = "giteaAdmin" SourceTypeLocal = "local" SourceTypeRemote = "remote" SourceTypeEmbedded = "embedded" ) type GitRepositorySpec struct { // +kubebuilder:validation:Optional Customization PackageCustomization `json:"customization,omitempty"` // SecretRef is the reference to secret that contain Git server credentials // +kubebuilder:validation:Optional SecretRef SecretReference `json:"secretRef"` Source GitRepositorySource `json:"source,omitempty"` Provider Provider `json:"provider"` } type GitRepositorySource struct { // +kubebuilder:validation:Enum:=argocd;gitea;nginx // +kubebuilder:validation:Optional EmbeddedAppName string `json:"embeddedAppName,omitempty"` // Path is the absolute path to directory that contains Kustomize structure or raw manifests. // This is required when Type is set to local. // +kubebuilder:validation:Optional Path string `json:"path"` RemoteRepository RemoteRepositorySpec `json:"remoteRepository"` // Type is the source type. // +kubebuilder:validation:Enum:=local;embedded;remote // +kubebuilder:default:=embedded Type string `json:"type"` } type Provider struct { // +kubebuilder:validation:Enum:=gitea;github // +kubebuilder:validation:Required Name string `json:"name"` // GitURL is the base URL of Git server used for API calls. // +kubebuilder:validation:Required // +kubebuilder:validation:Pattern=`^https?:\/\/.+$` GitURL string `json:"gitURL"` // InternalGitURL is the base URL of Git server accessible within the cluster only. InternalGitURL string `json:"internalGitURL"` OrganizationName string `json:"organizationName"` } type SecretReference struct { Name string `json:"name"` Namespace string `json:"namespace"` } type Commit struct { // Hash is the digest of the most recent commit // +kubebuilder:validation:Optional Hash string `json:"hash"` } type GitRepositoryStatus struct { // LatestCommit is the most recent commit known to the controller // +kubebuilder:validation:Optional LatestCommit Commit `json:"commit"` // ExternalGitRepositoryUrl is the url for the in-cluster repository accessible from local machine. // +kubebuilder:validation:Optional ExternalGitRepositoryUrl string `json:"externalGitRepositoryUrl"` // InternalGitRepositoryUrl is the url for the in-cluster repository accessible within the cluster. // +kubebuilder:validation:Optional InternalGitRepositoryUrl string `json:"internalGitRepositoryUrl"` // Path is the path within the repository that contains the files. // +kubebuilder:validation:Optional Path string `json:"path"` Synced bool `json:"synced"` } // +kubebuilder:object:root=true // +kubebuilder:subresource:status type GitRepository struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec GitRepositorySpec `json:"spec,omitempty"` Status GitRepositoryStatus `json:"status,omitempty"` } // +kubebuilder:object:root=true type GitRepositoryList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []GitRepository `json:"items"` } ================================================ FILE: api/v1alpha1/groupversion_info.go ================================================ // +kubebuilder:object:generate=true // +groupName=idpbuilder.cnoe.io package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/scheme" ) var ( // GroupVersion is group version used to register these objects GroupVersion = schema.GroupVersion{Group: "idpbuilder.cnoe.io", Version: "v1alpha1"} // 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 ) func init() { SchemeBuilder.Register(&Localbuild{}, &LocalbuildList{}) SchemeBuilder.Register(&GitRepository{}, &GitRepositoryList{}) SchemeBuilder.Register(&CustomPackage{}, &CustomPackageList{}) } ================================================ FILE: api/v1alpha1/localbuild_types.go ================================================ package v1alpha1 import ( "fmt" "github.com/cnoe-io/idpbuilder/globals" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( // LastObservedCLIStartTimeAnnotation indicates when the controller acted on a resource. LastObservedCLIStartTimeAnnotation = "cnoe.io/last-observed-cli-start-time" // CliStartTimeAnnotation indicates when the CLI was invoked. CliStartTimeAnnotation = "cnoe.io/cli-start-time" // PackagePriorityAnnotation indicates the priority of a package (higher = wins conflicts). PackagePriorityAnnotation = "cnoe.io/package-priority" // PackageSourcePathAnnotation indicates the source path of a package. PackageSourcePathAnnotation = "cnoe.io/package-source-path" FieldManager = "idpbuilder" // If GetSecretLabelKey is set to GetSecretLabelValue on a kubernetes secret, secret key and values can be used by the get command. CLISecretLabelKey = "cnoe.io/cli-secret" CLISecretLabelValue = "true" PackageNameLabelKey = "cnoe.io/package-name" PackageTypeLabelKey = "cnoe.io/package-type" PackageTypeLabelCore = "core" PackageTypeLabelCustom = "custom" ArgoCDPackageName = "argocd" GiteaPackageName = "gitea" IngressNginxPackageName = "nginx" ) // ArgoPackageConfigSpec Allows for configuration of the ArgoCD Installation. // If no fields are specified then the binary embedded resources will be used to install ArgoCD. type ArgoPackageConfigSpec struct { // Enabled controls whether to install ArgoCD. Enabled bool `json:"enabled,omitempty"` } // EmbeddedArgoApplicationsPackageConfigSpec Controls the installation of the embedded argo applications. type EmbeddedArgoApplicationsPackageConfigSpec struct { // Enabled controls whether to install the embedded argo applications and the associated GitServer Enabled bool `json:"enabled,omitempty"` } type PackageConfigsSpec struct { Argo ArgoPackageConfigSpec `json:"argoPackageConfigs,omitempty"` EmbeddedArgoApplications EmbeddedArgoApplicationsPackageConfigSpec `json:"embeddedArgoApplicationsPackageConfigs,omitempty"` CustomPackageFiles []string `json:"customPackageFiles,omitempty"` CustomPackageDirs []string `json:"customPackageDirs,omitempty"` CustomPackageUrls []string `json:"customPackageUrls,omitempty"` // +kubebuilder:validation:Optional CorePackageCustomization map[string]PackageCustomization `json:"packageCustomization,omitempty"` } // RegistryMirror defines an external registry mirror configuration type RegistryMirror struct { // TargetRegistry is the registry that should be mirrored (e.g., "docker.io", "ghcr.io") TargetRegistry string `json:"targetRegistry,omitempty"` // RegistryAddress is the address of the mirror registry (e.g., "http://kind-registry:5000") RegistryAddress string `json:"registryAddress,omitempty"` } // BuildCustomizationSpec fields cannot change once a cluster is created type BuildCustomizationSpec struct { Protocol string `json:"protocol,omitempty"` Host string `json:"host,omitempty"` IngressHost string `json:"ingressHost,omitempty"` Port string `json:"port,omitempty"` UsePathRouting bool `json:"usePathRouting,omitempty"` SelfSignedCert string `json:"selfSignedCert,omitempty"` StaticPassword bool `json:"staticPassword,omitempty"` RegistryMirrors []RegistryMirror `json:"registryMirrors,omitempty"` InsecureRegistryMirrors bool `json:"insecureRegistryMirrors,omitempty"` } type LocalbuildSpec struct { PackageConfigs PackageConfigsSpec `json:"packageConfigs,omitempty"` BuildCustomization BuildCustomizationSpec `json:"buildCustomization,omitempty"` } // PackageCustomization defines how packages are customized type PackageCustomization struct { // Name is the name of the package to be customized. e.g. argocd Name string `json:"name,omitempty'"` // FilePath is the absolute file path to a YAML file that contains Kubernetes manifests. FilePath string `json:"filePath,omitempty"` } type LocalbuildStatus struct { // ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. // +optional ObservedGeneration int64 `json:"observedGeneration,omitempty"` ArgoCD ArgoCDStatus `json:"ArgoCD,omitempty"` Nginx NginxStatus `json:"nginx,omitempty"` Gitea GiteaStatus `json:"gitea,omitempty"` } type GiteaStatus struct { Available bool `json:"available,omitempty"` ExternalURL string `json:"externalURL,omitempty"` InternalURL string `json:"internalURL,omitempty"` AdminUserSecretName string `json:"adminUserSecretNameecret,omitempty"` AdminUserSecretNamespace string `json:"adminUserSecretNamespace,omitempty"` } type ArgoCDStatus struct { Available bool `json:"available,omitempty"` AppsCreated bool `json:"appsCreated,omitempty"` } type NginxStatus struct { Available bool `json:"available,omitempty"` } // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:resource:path=localbuilds,scope=Cluster type Localbuild struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec LocalbuildSpec `json:"spec,omitempty"` Status LocalbuildStatus `json:"status,omitempty"` } func (l *Localbuild) GetArgoProjectName() string { return fmt.Sprintf("%s-%s-gitserver", globals.ProjectName, l.Name) } func (l *Localbuild) GetArgoApplicationName(name string) string { return fmt.Sprintf("%s-%s-gitserver-%s", globals.ProjectName, l.Name, name) } // +kubebuilder:object:root=true type LocalbuildList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []Localbuild `json:"items"` } ================================================ FILE: api/v1alpha1/zz_generated.deepcopy.go ================================================ //go:build !ignore_autogenerated /* Copyright 2023. 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 v1alpha1 import ( runtime "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ArgoCDPackageSpec) DeepCopyInto(out *ArgoCDPackageSpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgoCDPackageSpec. func (in *ArgoCDPackageSpec) DeepCopy() *ArgoCDPackageSpec { if in == nil { return nil } out := new(ArgoCDPackageSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ArgoCDStatus) DeepCopyInto(out *ArgoCDStatus) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgoCDStatus. func (in *ArgoCDStatus) DeepCopy() *ArgoCDStatus { if in == nil { return nil } out := new(ArgoCDStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ArgoPackageConfigSpec) DeepCopyInto(out *ArgoPackageConfigSpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgoPackageConfigSpec. func (in *ArgoPackageConfigSpec) DeepCopy() *ArgoPackageConfigSpec { if in == nil { return nil } out := new(ArgoPackageConfigSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BuildCustomizationSpec) DeepCopyInto(out *BuildCustomizationSpec) { *out = *in if in.RegistryMirrors != nil { in, out := &in.RegistryMirrors, &out.RegistryMirrors *out = make([]RegistryMirror, len(*in)) copy(*out, *in) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildCustomizationSpec. func (in *BuildCustomizationSpec) DeepCopy() *BuildCustomizationSpec { if in == nil { return nil } out := new(BuildCustomizationSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Commit) DeepCopyInto(out *Commit) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Commit. func (in *Commit) DeepCopy() *Commit { if in == nil { return nil } out := new(Commit) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomPackage) DeepCopyInto(out *CustomPackage) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomPackage. func (in *CustomPackage) DeepCopy() *CustomPackage { if in == nil { return nil } out := new(CustomPackage) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *CustomPackage) 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 *CustomPackageList) DeepCopyInto(out *CustomPackageList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]CustomPackage, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomPackageList. func (in *CustomPackageList) DeepCopy() *CustomPackageList { if in == nil { return nil } out := new(CustomPackageList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *CustomPackageList) 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 *CustomPackageSpec) DeepCopyInto(out *CustomPackageSpec) { *out = *in out.ArgoCD = in.ArgoCD out.GitServerAuthSecretRef = in.GitServerAuthSecretRef out.RemoteRepository = in.RemoteRepository } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomPackageSpec. func (in *CustomPackageSpec) DeepCopy() *CustomPackageSpec { if in == nil { return nil } out := new(CustomPackageSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomPackageStatus) DeepCopyInto(out *CustomPackageStatus) { *out = *in if in.GitRepositoryRefs != nil { in, out := &in.GitRepositoryRefs, &out.GitRepositoryRefs *out = make([]ObjectRef, len(*in)) copy(*out, *in) } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomPackageStatus. func (in *CustomPackageStatus) DeepCopy() *CustomPackageStatus { if in == nil { return nil } out := new(CustomPackageStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EmbeddedArgoApplicationsPackageConfigSpec) DeepCopyInto(out *EmbeddedArgoApplicationsPackageConfigSpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmbeddedArgoApplicationsPackageConfigSpec. func (in *EmbeddedArgoApplicationsPackageConfigSpec) DeepCopy() *EmbeddedArgoApplicationsPackageConfigSpec { if in == nil { return nil } out := new(EmbeddedArgoApplicationsPackageConfigSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GitRepository) DeepCopyInto(out *GitRepository) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec out.Status = in.Status } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepository. func (in *GitRepository) DeepCopy() *GitRepository { if in == nil { return nil } out := new(GitRepository) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *GitRepository) 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 *GitRepositoryList) DeepCopyInto(out *GitRepositoryList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]GitRepository, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepositoryList. func (in *GitRepositoryList) DeepCopy() *GitRepositoryList { if in == nil { return nil } out := new(GitRepositoryList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *GitRepositoryList) 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 *GitRepositorySource) DeepCopyInto(out *GitRepositorySource) { *out = *in out.RemoteRepository = in.RemoteRepository } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepositorySource. func (in *GitRepositorySource) DeepCopy() *GitRepositorySource { if in == nil { return nil } out := new(GitRepositorySource) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GitRepositorySpec) DeepCopyInto(out *GitRepositorySpec) { *out = *in out.Customization = in.Customization out.SecretRef = in.SecretRef out.Source = in.Source out.Provider = in.Provider } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepositorySpec. func (in *GitRepositorySpec) DeepCopy() *GitRepositorySpec { if in == nil { return nil } out := new(GitRepositorySpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GitRepositoryStatus) DeepCopyInto(out *GitRepositoryStatus) { *out = *in out.LatestCommit = in.LatestCommit } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitRepositoryStatus. func (in *GitRepositoryStatus) DeepCopy() *GitRepositoryStatus { if in == nil { return nil } out := new(GitRepositoryStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GiteaStatus) DeepCopyInto(out *GiteaStatus) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GiteaStatus. func (in *GiteaStatus) DeepCopy() *GiteaStatus { if in == nil { return nil } out := new(GiteaStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Localbuild) DeepCopyInto(out *Localbuild) { *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 Localbuild. func (in *Localbuild) DeepCopy() *Localbuild { if in == nil { return nil } out := new(Localbuild) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *Localbuild) 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 *LocalbuildList) DeepCopyInto(out *LocalbuildList) { *out = *in out.TypeMeta = in.TypeMeta in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Localbuild, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalbuildList. func (in *LocalbuildList) DeepCopy() *LocalbuildList { if in == nil { return nil } out := new(LocalbuildList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *LocalbuildList) 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 *LocalbuildSpec) DeepCopyInto(out *LocalbuildSpec) { *out = *in in.PackageConfigs.DeepCopyInto(&out.PackageConfigs) in.BuildCustomization.DeepCopyInto(&out.BuildCustomization) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalbuildSpec. func (in *LocalbuildSpec) DeepCopy() *LocalbuildSpec { if in == nil { return nil } out := new(LocalbuildSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalbuildStatus) DeepCopyInto(out *LocalbuildStatus) { *out = *in out.ArgoCD = in.ArgoCD out.Nginx = in.Nginx out.Gitea = in.Gitea } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalbuildStatus. func (in *LocalbuildStatus) DeepCopy() *LocalbuildStatus { if in == nil { return nil } out := new(LocalbuildStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NginxStatus) DeepCopyInto(out *NginxStatus) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NginxStatus. func (in *NginxStatus) DeepCopy() *NginxStatus { if in == nil { return nil } out := new(NginxStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectRef) DeepCopyInto(out *ObjectRef) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectRef. func (in *ObjectRef) DeepCopy() *ObjectRef { if in == nil { return nil } out := new(ObjectRef) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PackageConfigsSpec) DeepCopyInto(out *PackageConfigsSpec) { *out = *in out.Argo = in.Argo out.EmbeddedArgoApplications = in.EmbeddedArgoApplications if in.CustomPackageFiles != nil { in, out := &in.CustomPackageFiles, &out.CustomPackageFiles *out = make([]string, len(*in)) copy(*out, *in) } if in.CustomPackageDirs != nil { in, out := &in.CustomPackageDirs, &out.CustomPackageDirs *out = make([]string, len(*in)) copy(*out, *in) } if in.CustomPackageUrls != nil { in, out := &in.CustomPackageUrls, &out.CustomPackageUrls *out = make([]string, len(*in)) copy(*out, *in) } if in.CorePackageCustomization != nil { in, out := &in.CorePackageCustomization, &out.CorePackageCustomization *out = make(map[string]PackageCustomization, len(*in)) for key, val := range *in { (*out)[key] = val } } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PackageConfigsSpec. func (in *PackageConfigsSpec) DeepCopy() *PackageConfigsSpec { if in == nil { return nil } out := new(PackageConfigsSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PackageCustomization) DeepCopyInto(out *PackageCustomization) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PackageCustomization. func (in *PackageCustomization) DeepCopy() *PackageCustomization { if in == nil { return nil } out := new(PackageCustomization) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Provider) DeepCopyInto(out *Provider) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Provider. func (in *Provider) DeepCopy() *Provider { if in == nil { return nil } out := new(Provider) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RegistryMirror) DeepCopyInto(out *RegistryMirror) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryMirror. func (in *RegistryMirror) DeepCopy() *RegistryMirror { if in == nil { return nil } out := new(RegistryMirror) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RemoteRepositorySpec) DeepCopyInto(out *RemoteRepositorySpec) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteRepositorySpec. func (in *RemoteRepositorySpec) DeepCopy() *RemoteRepositorySpec { if in == nil { return nil } out := new(RemoteRepositorySpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretReference) DeepCopyInto(out *SecretReference) { *out = *in } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretReference. func (in *SecretReference) DeepCopy() *SecretReference { if in == nil { return nil } out := new(SecretReference) in.DeepCopyInto(out) return out } ================================================ FILE: docs/images/source/idpbuilder.excalidraw ================================================ { "type": "excalidraw", "version": 2, "source": "https://excalidraw.com", "elements": [ { "type": "rectangle", "version": 724, "versionNonce": 1733856607, "isDeleted": false, "id": "rn5VxKirQVQTGadXpV6do", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 1, "opacity": 100, "angle": 0, "x": 290.851641955539, "y": -205.70273211471522, "strokeColor": "#1971c2", "backgroundColor": "transparent", "width": 734.3860626220707, "height": 402.964050292969, "seed": 1808569105, "groupIds": [], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "id": "14YqOkt6L4M1dDmR0ETLV", "type": "arrow" }, { "id": "QKW8LI503Bc2mGvHDoU9l", "type": "arrow" }, { "id": "Bvu5NEGthDTE0Lox0pKMY", "type": "arrow" }, { "id": "nHmMkx97YgjINcsVC4VlS", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 1208, "versionNonce": 990927288, "isDeleted": false, "id": "ZGIq8yJ3BbmfwBJLKF255", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 335.41134196774556, "y": -142.72070696823084, "strokeColor": "#f08c00", "backgroundColor": "transparent", "width": 128.3000030517578, "height": 45, "seed": 1137314033, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158952, "link": null, "locked": false, "fontSize": 36, "fontFamily": 1, "text": "ArgoCD", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "ArgoCD", "lineHeight": 1.25, "baseline": 32 }, { "type": "line", "version": 943, "versionNonce": 1893290495, "isDeleted": false, "id": "c2F8xEpYpiskw9d3M9a8w", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 316.71289927073803, "y": -244.03680215324493, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 95.45497317148764, "height": 92.84673785134679, "seed": 207471313, "groupIds": [ "ErJ6hMmjgHu3hLAgUD5mh", "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ -2.460961781613241, 0.6518708205633831 ], [ -35.78710995652396, 16.547951146090107 ], [ -35.78710995652396, 16.547951146090107 ], [ -37.99651824523383, 18.295368383544606 ], [ -39.22587770163469, 20.829964132840722 ], [ -47.38323404404179, 56.50643421214563 ], [ -47.38323404404179, 56.50643421214563 ], [ -47.44490761168415, 59.02869632175984 ], [ -46.486164083674566, 61.371546036703016 ], [ -46.127336086160476, 61.87390302314864 ], [ -23.102541153377942, 90.5023995445162 ], [ -23.102541153377942, 90.5023995445162 ], [ -20.88341281591535, 92.2385995862048 ], [ -18.13277162331118, 92.84673785134694 ], [ 18.796609460770327, 92.84673785134657 ], [ 18.796609460770327, 92.84673785134657 ], [ 21.553601408419915, 92.21505588002745 ], [ 23.7723561720563, 90.47548511877764 ], [ 46.7851882763901, 61.84101141619088 ], [ 46.7851882763901, 61.84101141619088 ], [ 48.01006555980353, 59.31202497770516 ], [ 47.98128041322563, 56.5004570309265 ], [ 39.770104899555754, 20.794081083564848 ], [ 39.770104899555754, 20.794081083564848 ], [ 38.538497583853335, 18.259485334268803 ], [ 36.33133216395502, 16.51206809681414 ], [ 3.0590107017396324, 0.6548610152590679 ], [ 3.0590107017396324, 0.6548610152590679 ], [ -0.029900164639430578, 1.0408340855860843e-17 ], [ 0, 0 ] ] }, { "type": "line", "version": 1459, "versionNonce": 1660729887, "isDeleted": false, "id": "-sn-l6KrmGQBkTSK90eC2", "fillStyle": "solid", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 316.71182092183017, "y": -232.215284031392, "strokeColor": "#326ce5", "backgroundColor": "#fff", "width": 69.89576554459413, "height": 68.58285031337438, "seed": 1646215345, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ -1.432324825301546, 0.706068790071741 ], [ -1.9586047951674281, 2.2127733048543057 ], [ -1.9586047951674281, 2.7749363239961387 ], [ -1.9586047951674281, 2.7749363239961387 ], [ -1.6835033185244077, 4.667755053539658 ], [ -1.4861479733611118, 8.285937332102842 ], [ -2.138020041547117, 9.317567156587057 ], [ -2.1828717143605587, 10.1608131111541 ], [ -2.1828717143605587, 10.1608131111541 ], [ -5.780122451821784, 10.716997523222345 ], [ -9.423676381772387, 11.828850188102779 ], [ -12.844922516336029, 13.45792009292789 ], [ -15.98864037024059, 15.574210114965936 ], [ -18.799598051379608, 18.14772598319378 ], [ -19.517253333480934, 17.639386112111524 ], [ -19.517253333480934, 17.639386112111524 ], [ -20.698396813851012, 17.519776898427985 ], [ -23.380636924047703, 15.0976867567003 ], [ -24.687368225174932, 13.707230717019739 ], [ -25.129922030633214, 13.354383108896979 ], [ -25.129922030633214, 13.354383108896979 ], [ -26.51439946324018, 12.831091729640708 ], [ -28.102213699792635, 13.536786945886227 ], [ -28.46477993081394, 15.107405379598852 ], [ -27.611815353348355, 16.476185582233697 ], [ -27.199163138383813, 16.805110206936313 ], [ -27.199163138383813, 16.805110206936313 ], [ -25.548554278525646, 17.770955391650862 ], [ -22.56430111765615, 19.864120908675922 ], [ -22.166601836719924, 21.01236993037974 ], [ -21.51472976853398, 21.610415998797468 ], [ -21.51472976853398, 21.610415998797468 ], [ -23.76100352013141, 25.760906759200605 ], [ -25.20355599831609, 30.21443718537146 ], [ -25.816881521396525, 34.85579539828312 ], [ -25.57546727840974, 39.56975526036552 ], [ -26.4127317741946, 39.808973687732575 ], [ -26.4127317741946, 39.808973687732575 ], [ -27.26793922047171, 40.67016116693759 ], [ -30.838276958048898, 41.25923861181782 ], [ -32.75202722869432, 41.40874799014082 ], [ -33.281297215024175, 41.528360055533014 ], [ -33.34110182186594, 41.528360055533014 ], [ -33.34110182186594, 41.528360055533014 ], [ -34.32277541514808, 41.949032700926544 ], [ -34.92197214798472, 42.75908334157035 ], [ -34.64656696437611, 44.74352461662653 ], [ -34.4983223188159, 44.91330393965695 ], [ -33.54564347269364, 45.450098159119925 ], [ -32.45300276863114, 45.406689450856575 ], [ -32.414129702891266, 45.406689450856575 ], [ -31.875888241315288, 45.34688912157768 ], [ -31.875888241315288, 45.34688912157768 ], [ -30.087728643135613, 44.695017053391766 ], [ -26.613077135821825, 43.67833731122727 ], [ -25.4708081470459, 44.08201947679996 ], [ -24.57373904441927, 43.93250439505977 ], [ -24.57373904441927, 43.93250439505977 ], [ -22.726614667579607, 48.26815659466553 ], [ -20.14894100821738, 52.1676114472755 ], [ -16.913041673915092, 55.54003062724162 ], [ -13.09124454981824, 58.29459862258373 ], [ -13.456052223796778, 59.05710557749845 ], [ -13.456052223796778, 59.05710557749845 ], [ -13.27663697741718, 60.18143161578213 ], [ -15.079749509625142, 63.44676913793114 ], [ -16.15025239984924, 65.04056055570291 ], [ -16.404422335390343, 65.5788034431332 ], [ -16.404422335390343, 65.5788034431332 ], [ -16.674844158225717, 66.61201739174305 ], [ -16.40310484601853, 67.58225991111416 ], [ -15.697771796764803, 68.30179161747229 ], [ -14.667403853334795, 68.58285031337438 ], [ -14.460769048396918, 68.57203093095742 ], [ -13.451326942651566, 68.15994192844089 ], [ -12.807171597929074, 67.28024686044131 ], [ -12.55898169531586, 66.77190698935901 ], [ -12.55898169531586, 66.77190698935901 ], [ -11.984855758609651, 64.94786291604923 ], [ -11.287758443784064, 62.994870283400545 ], [ -10.44488748889749, 61.37154657139842 ], [ -9.58968004262038, 60.95291574936029 ], [ -9.14114620423424, 60.13657994296869 ], [ -9.14114620423424, 60.13657994296869 ], [ -4.608275541477875, 61.41782409851035 ], [ 0.04370528595749003, 61.85256707412143 ], [ 4.697756453834344, 61.440535105776746 ], [ 9.236826731080514, 60.18143161578213 ], [ 9.634531715433956, 60.94394427411406 ], [ 9.634531715433956, 60.94394427411406 ], [ 10.651205754181227, 61.55694185070587 ], [ 12.014755923249211, 64.90599983384534 ], [ 12.594861892883253, 66.73303249776492 ], [ 12.843051795496526, 67.24137236884712 ], [ 12.843051795496526, 67.24137236884712 ], [ 13.470404873165572, 68.10570813434327 ], [ 14.392915494040242, 68.51092451914111 ], [ 16.267309334338545, 67.80347835381698 ], [ 16.392453714408873, 67.63309446856408 ], [ 16.712478156580296, 66.59177596412158 ], [ 16.440299681249144, 65.53694036092938 ], [ 16.180149712780135, 64.9986974734991 ], [ 16.180149712780135, 64.9986974734991 ], [ 15.109646822556089, 63.41088323694667 ], [ 13.315505765594258, 60.25020912372438 ], [ 13.518843995393977, 59.05411698688884 ], [ 13.186927928373212, 58.24974124635304 ], [ 16.998681334791385, 55.478405204460664 ], [ 20.222572124191764, 52.091733184926845 ], [ 22.78655473057989, 48.18083157400843 ], [ 24.618589291378605, 43.83681816479638 ], [ 25.46781100131068, 43.98633324653653 ], [ 25.46781100131068, 43.98633324653653 ], [ 26.583171267765383, 43.573679605717764 ], [ 30.057824200933453, 44.590359347882234 ], [ 31.845982373258824, 45.27811161363543 ], [ 32.36029942556033, 45.38875220378148 ], [ 32.39917391715455, 45.38875220378148 ], [ 32.39917391715455, 45.38875220378148 ], [ 33.46608365454636, 45.437236953347536 ], [ 34.358103807102054, 44.968701230862074 ], [ 34.91430675527615, 44.12855365768571 ], [ 34.97379339660941, 43.06219715176162 ], [ 34.913958846827356, 42.844064257760614 ], [ 34.28972553836342, 41.946580231533176 ], [ 33.287275822097925, 41.5104171050407 ], [ 32.707169852463785, 41.372867792573494 ], [ 32.707169852463785, 41.372867792573494 ], [ 30.79341673010979, 41.22335271083331 ], [ 27.223083270095493, 40.63428096937031 ], [ 26.361895790890525, 39.77309349016526 ], [ 25.55453145974511, 39.53387506279818 ], [ 25.55453145974511, 39.53387506279818 ], [ 25.766601621268805, 34.82487147025736 ], [ 25.129050833656983, 30.192795568828938 ], [ 23.668126222836204, 25.751142508964527 ], [ 21.410069211315992, 21.61340744111573 ], [ 22.11576442756147, 20.961535372929777 ], [ 22.11576442756147, 20.961535372929777 ], [ 22.486549282759302, 19.831226450009634 ], [ 25.446879460208716, 17.75002385054896 ], [ 27.09748832006682, 16.784178665834418 ], [ 27.534062092597303, 16.431331057711628 ], [ 27.534062092597303, 16.431331057711628 ], [ 28.479973834218885, 14.665236554801158 ], [ 28.198555823033498, 13.697754489351949 ], [ 27.423444316119998, 12.963008917628864 ], [ 27.136362811661037, 12.837071762568605 ], [ 26.02624968902474, 12.777268581581119 ], [ 25.05516306390892, 13.318500059621057 ], [ 24.612606406742078, 13.67134766774382 ], [ 24.612606406742078, 13.67134766774382 ], [ 23.30587367976053, 15.06180655913298 ], [ 20.695402519824324, 17.52276834074621 ], [ 19.487344613715795, 17.654337620285542 ], [ 18.730820543437513, 18.19258050771583 ], [ 18.730820543437513, 18.19258050771583 ], [ 15.189352077842008, 15.094883527149458 ], [ 11.181977165087368, 12.698025303087958 ], [ 6.811283170241874, 11.052463967446453 ], [ 2.1798802720422907, 10.208656226285797 ], [ 2.135022895811664, 9.320557173051004 ], [ 1.4831508276257466, 8.327800414306662 ], [ 1.7104091891370812, 4.718588185135307 ], [ 1.9855135174886707, 2.825770881446082 ], [ 1.9855135174886707, 2.227724813028326 ], [ 1.9855135174886707, 2.227724813028326 ], [ 1.4603542691014244, 0.7210202982457582 ], [ 0.026908722321194466, 0.0149515081740186 ], [ 0, 0 ] ] }, { "type": "line", "version": 1107, "versionNonce": 1757290047, "isDeleted": false, "id": "0zj6xQuydJV84vNPw3a0y", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 314.2267921933967, "y": -216.52528173709106, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 11.99681582446548, "height": 11.951961299943425, "seed": 1656095377, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ -0.598046068417764, 10.444884637188963 ], [ -0.6429005929397977, 10.444884637189041 ], [ -0.6429005929397977, 10.444884637189041 ], [ -1.635657351684161, 11.95196129994343 ], [ -3.4297984086460485, 11.790489004056063 ], [ -11.99681582446549, 5.720316419125781 ], [ -11.99681582446549, 5.720316419125781 ], [ -7.434318761095046, 2.340488500224822 ], [ -2.120077091054865, 0.3408846905583963 ], [ -0.005980032927881736, 9.941700240823081e-15 ], [ 0, 0 ] ] }, { "type": "line", "version": 1105, "versionNonce": 1425931871, "isDeleted": false, "id": "BDoCa--PCN_pGPu0n0vxp", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 319.34931079417174, "y": -216.7677382571792, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 11.93102975884153, "height": 11.999804415075133, "seed": 182028401, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ 6.437595275692294, 1.8965544678055735 ], [ 11.931029758841582, 5.753208026083467 ], [ 3.4447499168200473, 11.784508971128222 ], [ 3.4447499168200473, 11.784508971128222 ], [ 1.596785711798569, 11.999804415075136 ], [ 0.8701589544511403, 11.359895264453584 ], [ 0.5920660354898679, 10.432921719624602 ], [ 0, 0 ] ] }, { "type": "line", "version": 1109, "versionNonce": 1250744959, "isDeleted": false, "id": "aM2pb5buDydJO5vIZU7Xh", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 299.2709047804233, "y": -207.02849463627263, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 11.300092083466069, "height": 12.977612517354048, "seed": 1414615633, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 7.8344106255441055, 6.991163245122797 ], [ 7.8344106255441455, 7.03601776964485 ], [ 7.8344106255441455, 7.03601776964485 ], [ 8.390593611758083, 8.752412695127 ], [ 7.143666917472586, 10.053165389180608 ], [ 7.143666917472592, 10.083062702111473 ], [ -2.909498471708001, 12.974621075035827 ], [ -2.909498471708001, 12.974621075035827 ], [ -2.534264951098859, 6.243208559178456 ], [ 0.0029885906096372024, -0.002991442318245268 ], [ 0, 0 ] ] }, { "type": "line", "version": 1107, "versionNonce": 1043018399, "isDeleted": false, "id": "ZMKPKTRRnwiHqgBmqk9Ku", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 334.25551510026025, "y": -207.02430181169802, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 11.315043591640089, "height": 12.938735174051288, "seed": 334815281, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ 2.5544065689194433, 6.224917700237365 ], [ 2.996216078433857, 12.938735174051327 ], [ -7.071900818920772, 10.038211029298026 ], [ -7.071900818920771, 9.99933653770387 ], [ -7.071900818920771, 9.99933653770387 ], [ -8.318827513206253, 8.69858669535882 ], [ -7.7626416752837, 6.9821946215852595 ], [ 0.011960065855774405, 0.023920131711560263 ], [ 0, 0 ] ] }, { "type": "line", "version": 1106, "versionNonce": 948537023, "isDeleted": false, "id": "nxsrvolaIiv2iExwpG_vq", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 315.10606373478595, "y": -199.58286886808946, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 7.1556269833283865, "height": 6.982197473293844, "seed": 397128209, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 3.2055314894529396, -1.1102230246251565e-15 ], [ 5.164130581203231, 2.487876207351637 ], [ 4.452458183738401, 5.597715763123981 ], [ 1.5728627283784298, 6.98219747329385 ], [ -1.312712759909417, 5.597715763123977 ], [ -1.9914964021251595, 2.4878762073516323 ], [ 0, 0 ] ] }, { "type": "line", "version": 1108, "versionNonce": 1481135839, "isDeleted": false, "id": "Paw3M3HwuulNv623fueDx", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 325.3745245679115, "y": -191.0965890260677, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 12.304808908066201, "height": 12.19417402133738, "seed": 74270705, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ 0.4036821655727135, 2.7755575615628914e-15 ], [ 10.770817819573345, 1.7492893841484127 ], [ 10.770817819573345, 1.7492893841484127 ], [ 9.385126984958402, 4.851794345409312 ], [ 7.505486000841536, 7.663596132293022 ], [ 5.18403550721024, 10.129462852693091 ], [ 2.472921847469034, 12.1941740213374 ], [ -1.5339910884928634, 2.49385909198812 ], [ -1.5339910884928634, 2.49385909198812 ], [ -1.4077573557385041, 0.8748471633845953 ], [ -0.011960065855776133, 0.044857376230654375 ], [ 0, 0 ] ] }, { "type": "line", "version": 1106, "versionNonce": 335028991, "isDeleted": false, "id": "sEZR59QTYvH1q70VhVpuN", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 308.1107476911061, "y": -190.8484195689607, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 12.230054218904701, "height": 12.107453562902904, "seed": 1950425553, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ 1.4472734817670032, 0.801381446508931 ], [ 1.5878142365524563, 2.446007421730604 ], [ 1.587814236552457, 2.4848819133247853 ], [ -2.395178567697883, 12.107453562902913 ], [ -2.395178567697883, 12.107453562902913 ], [ -7.370925278983947, 7.620609476901985 ], [ -10.642239982352251, 1.7702152218331175 ], [ -0.3648076739785433, 0.026908722321190404 ], [ -0.3648076739785433, 0.026908722321190404 ], [ -0.017942950492249525, 0.026908722321187968 ], [ 0, 0 ] ] }, { "type": "line", "version": 1110, "versionNonce": 1008298783, "isDeleted": false, "id": "2SpVvudZ8y4_Re0DhpGuH", "fillStyle": "cross-hatch", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, "opacity": 100, "angle": 0, "x": 316.75014343286284, "y": -186.8614219006986, "strokeColor": "#326ce5", "backgroundColor": "#326ce5", "width": 13.261688320951794, "height": 11.151697723204514, "seed": 1413398449, "groupIds": [ "yCr05koDdbRalXjQDOhWf" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "startBinding": null, "endBinding": null, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": null, "points": [ [ 0, 0 ], [ 0, 0 ], [ 0.9333756306292258, 0.23297888895687952 ], [ 1.6057571870447254, 0.9209935119010776 ], [ 1.6446316786388921, 0.9209935119010871 ], [ 6.710087438969065, 10.062134012718186 ], [ 4.685699429886235, 10.660182932844489 ], [ 4.685699429886235, 10.660182932844489 ], [ -0.9721987914686103, 11.151697723204538 ], [ -6.5516008819827345, 10.080076963210427 ], [ -1.4682021711602933, 0.9389307589761464 ], [ -1.4682021711602933, 0.9389307589761464 ], [ 0.026914425738386212, 0.05681173866922885 ], [ 0, 0 ] ] }, { "type": "rectangle", "version": 747, "versionNonce": 1025290047, "isDeleted": false, "id": "ovJ_8JRWUYtl5SwIsoTD6", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 692.0446732665741, "y": -115.22070696823084, "strokeColor": "#1e1e1e", "backgroundColor": "#b2f2bb", "width": 304.9999999999999, "height": 257.9999999999999, "seed": 42836369, "groupIds": [], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "id": "Bvu5NEGthDTE0Lox0pKMY", "type": "arrow" }, { "id": "6KxS52QdlYIpoAD1U0DXi", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "rectangle", "version": 267, "versionNonce": 518480799, "isDeleted": false, "id": "gO4o6gRc5z57hSlRJcNHT", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 564.7363621104851, "y": 276.1118915651209, "strokeColor": "#2f9e44", "backgroundColor": "transparent", "width": 189, "height": 116, "seed": 744834929, "groupIds": [], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "type": "text", "id": "b0yoow8nriD3ymO5GaMiK" }, { "id": "tJR6pa6ndvgR0PAy_y0T6", "type": "arrow" }, { "id": "QKW8LI503Bc2mGvHDoU9l", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 294, "versionNonce": 758987192, "isDeleted": false, "id": "b0yoow8nriD3ymO5GaMiK", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 595.203029285778, "y": 299.1118915651209, "strokeColor": "#2f9e44", "backgroundColor": "transparent", "width": 128.06666564941406, "height": 70, "seed": 1812803921, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500141084, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "Core \nPackages", "textAlign": "center", "verticalAlign": "middle", "containerId": "gO4o6gRc5z57hSlRJcNHT", "originalText": "Core Packages", "lineHeight": 1.25, "baseline": 60 }, { "type": "rectangle", "version": 96, "versionNonce": 414522399, "isDeleted": false, "id": "-TheK_iiszzs08UFHds1X", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 534.7363621104846, "y": 631.1118915651214, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 275.0000000000001, "height": 121, "seed": 652009265, "groupIds": [], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "type": "text", "id": "BEuOD-IEnvFbbjGNWOgDJ" }, { "id": "14YqOkt6L4M1dDmR0ETLV", "type": "arrow" }, { "id": "tJR6pa6ndvgR0PAy_y0T6", "type": "arrow" }, { "id": "Bvu5NEGthDTE0Lox0pKMY", "type": "arrow" }, { "id": "nHmMkx97YgjINcsVC4VlS", "type": "arrow" }, { "id": "4AOkOmojUQrdiA36lQ8DU", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 110, "versionNonce": 1293566015, "isDeleted": false, "id": "BEuOD-IEnvFbbjGNWOgDJ", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 546.3696934093127, "y": 674.1118915651214, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 251.73333740234375, "height": 35, "seed": 725340433, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "IDPBUILDER CLI", "textAlign": "center", "verticalAlign": "middle", "containerId": "-TheK_iiszzs08UFHds1X", "originalText": "IDPBUILDER CLI", "lineHeight": 1.25, "baseline": 25 }, { "type": "arrow", "version": 249, "versionNonce": 1259703281, "isDeleted": false, "id": "14YqOkt6L4M1dDmR0ETLV", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 549.7363621104851, "y": 626.1118915651214, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 168, "height": 419, "seed": 245466865, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [ { "type": "text", "id": "iCi0zfwHPwogLyCB1WOxr" } ], "updated": 1702423269709, "link": null, "locked": false, "startBinding": { "elementId": "-TheK_iiszzs08UFHds1X", "focus": -0.2645777715329469, "gap": 5 }, "endBinding": { "elementId": "rn5VxKirQVQTGadXpV6do", "focus": 0.14877182187672447, "gap": 9.850573386867609 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ -168, -159 ], [ -53.026868283065824, -419 ] ] }, { "type": "text", "version": 47, "versionNonce": 52195519, "isDeleted": false, "id": "iCi0zfwHPwogLyCB1WOxr", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1331.7446934093132, "y": 446.11189156512137, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 165.98333740234375, "height": 70, "seed": 1268089041, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423259436, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "1. Craete\nKind Cluster", "textAlign": "center", "verticalAlign": "middle", "containerId": "14YqOkt6L4M1dDmR0ETLV", "originalText": "1. Craete\nKind Cluster", "lineHeight": 1.25, "baseline": 60 }, { "type": "arrow", "version": 296, "versionNonce": 2024145841, "isDeleted": false, "id": "tJR6pa6ndvgR0PAy_y0T6", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 662.3990797216493, "y": 627.1118915651214, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 9.749588133858879, "height": 228, "seed": 531578545, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [ { "type": "text", "id": "mcDZHNEZRhnaca9qy1QuG" } ], "updated": 1702423269709, "link": null, "locked": false, "startBinding": { "elementId": "-TheK_iiszzs08UFHds1X", "focus": -0.08991115524671474, "gap": 4 }, "endBinding": { "elementId": "gO4o6gRc5z57hSlRJcNHT", "focus": -0.16180416542442702, "gap": 7.000000000000455 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ 9.749588133858879, -228 ] ] }, { "type": "text", "version": 25, "versionNonce": 777321311, "isDeleted": false, "id": "mcDZHNEZRhnaca9qy1QuG", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1633.0822081391648, "y": 509.61189156512137, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 134.38333129882812, "height": 35, "seed": 697712785, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423259438, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "2. Install", "textAlign": "center", "verticalAlign": "middle", "containerId": "tJR6pa6ndvgR0PAy_y0T6", "originalText": "2. Install", "lineHeight": 1.25, "baseline": 25 }, { "type": "arrow", "version": 337, "versionNonce": 181111665, "isDeleted": false, "id": "QKW8LI503Bc2mGvHDoU9l", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 664.3720761060194, "y": 270.1118915651209, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 3.197125404118765, "height": 71.85057338686784, "seed": 1191315057, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [], "updated": 1702423269709, "link": null, "locked": false, "startBinding": { "elementId": "gO4o6gRc5z57hSlRJcNHT", "focus": 0.08223574565392806, "gap": 6 }, "endBinding": { "elementId": "rn5VxKirQVQTGadXpV6do", "focus": 0.015630487251397887, "gap": 1 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ -3.197125404118765, -71.85057338686784 ] ] }, { "type": "arrow", "version": 832, "versionNonce": 193078065, "isDeleted": false, "id": "Bvu5NEGthDTE0Lox0pKMY", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 810.7363621104851, "y": 676.1118915651214, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 90, "height": 525.9999999999991, "seed": 851054673, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [ { "type": "text", "id": "ZsF0PE77YsQf6RTxSi4T7" } ], "updated": 1702423269709, "link": null, "locked": false, "startBinding": { "elementId": "-TheK_iiszzs08UFHds1X", "focus": 0.8084116201763285, "gap": 1.000000000000398 }, "endBinding": { "elementId": "ovJ_8JRWUYtl5SwIsoTD6", "focus": 0.0439116734429434, "gap": 7.332598533353234 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ 90, -212 ], [ 45.5918098316173, -525.9999999999991 ] ] }, { "type": "text", "version": 100, "versionNonce": 972830591, "isDeleted": false, "id": "ZsF0PE77YsQf6RTxSi4T7", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1782.6363560069694, "y": 408.11189156512137, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 302.20001220703125, "height": 140, "seed": 1653988913, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423259439, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "3. Create \nRepositories and hand\nover control to \nArgoCD", "textAlign": "center", "verticalAlign": "middle", "containerId": "Bvu5NEGthDTE0Lox0pKMY", "originalText": "3. Create Repositories and hand over control to ArgoCD", "lineHeight": 1.25, "baseline": 130 }, { "type": "text", "version": 247, "versionNonce": 343496, "isDeleted": false, "id": "n4KQJWFb5VyJNlsy8wI_H", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 795.7363621104851, "y": -34.88810843487863, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", "width": 164.06666564941406, "height": 150, "seed": 628944913, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158953, "link": null, "locked": false, "fontSize": 20, "fontFamily": 1, "text": "Git Repositories:\n- ArgoCD\n- Ingress-nginx\n- Gitea\n- Backstage\n- Crossplane", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "Git Repositories:\n- ArgoCD\n- Ingress-nginx\n- Gitea\n- Backstage\n- Crossplane", "lineHeight": 1.25, "baseline": 143 }, { "type": "text", "version": 198, "versionNonce": 1548509880, "isDeleted": false, "id": "J6fygoVPW4s-Zz324ipKh", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 346.73636211048506, "y": -75.88810843487863, "strokeColor": "#f08c00", "backgroundColor": "transparent", "width": 142.3000030517578, "height": 150, "seed": 23512561, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158953, "link": null, "locked": false, "fontSize": 20, "fontFamily": 1, "text": "ArgoCD Apps:\n- ArgoCD\n- Ingress-nginx\n- Gitea\n- Backstage\n- Crossplane", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "ArgoCD Apps:\n- ArgoCD\n- Ingress-nginx\n- Gitea\n- Backstage\n- Crossplane", "lineHeight": 1.25, "baseline": 143 }, { "type": "rectangle", "version": 179, "versionNonce": 2047916479, "isDeleted": false, "id": "axsfnFtRU5tBoleN1koKQ", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 322.73636211048506, "y": -149.88810843487863, "strokeColor": "#f08c00", "backgroundColor": "transparent", "width": 184.00000000000003, "height": 253, "seed": 1364910033, "groupIds": [], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "id": "6KxS52QdlYIpoAD1U0DXi", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 106, "versionNonce": 1838061055, "isDeleted": false, "id": "JX7B2x-Lgx3YrqjriOdqF", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 713.7363621104851, "y": -107.88810843487863, "strokeColor": "#1e1e1e", "backgroundColor": "transparent", "width": 100.33333587646484, "height": 45, "seed": 594591153, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false, "fontSize": 36, "fontFamily": 1, "text": "Gitea", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "Gitea", "lineHeight": 1.25, "baseline": 32 }, { "type": "arrow", "version": 174, "versionNonce": 902154993, "isDeleted": false, "id": "6KxS52QdlYIpoAD1U0DXi", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 510.7363621104846, "y": -42.88810843487863, "strokeColor": "#f08c00", "backgroundColor": "transparent", "width": 176, "height": 8, "seed": 1456463761, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [], "updated": 1702423269710, "link": null, "locked": false, "startBinding": { "elementId": "axsfnFtRU5tBoleN1koKQ", "focus": -0.18260869565217372, "gap": 3.9999999999995453 }, "endBinding": { "elementId": "ovJ_8JRWUYtl5SwIsoTD6", "focus": 0.3052581578699753, "gap": 5.308311156089587 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ 176, 8 ] ] }, { "type": "text", "version": 87, "versionNonce": 657081544, "isDeleted": false, "id": "F-QKzwRSJ7Pb6RMm1vBsC", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 560.7363621104851, "y": -74.88810843487863, "strokeColor": "#f08c00", "backgroundColor": "transparent", "width": 66.69999694824219, "height": 25, "seed": 2041562481, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158954, "link": null, "locked": false, "fontSize": 20, "fontFamily": 1, "text": "GitOps", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "GitOps", "lineHeight": 1.25, "baseline": 18 }, { "type": "rectangle", "version": 399, "versionNonce": 1762247263, "isDeleted": false, "id": "a1YtLmme14ISmpN-GNiiT", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 32.23636211048506, "y": 216.1118915651209, "strokeColor": "#2f9e44", "backgroundColor": "transparent", "width": 240, "height": 126.00000000000014, "seed": 1733816145, "groupIds": [ "3NGajuyekE1K_G5zxIRhq" ], "frameId": null, "roundness": { "type": 3 }, "boundElements": [], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 263, "versionNonce": 268271288, "isDeleted": false, "id": "Ph6f2fAmMNTsoBkG0jrmd", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 45.73636211048506, "y": 229.1118915651209, "strokeColor": "#2f9e44", "backgroundColor": "transparent", "width": 149.8000030517578, "height": 100, "seed": 639622449, "groupIds": [ "3NGajuyekE1K_G5zxIRhq" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500151458, "link": null, "locked": false, "fontSize": 20, "fontFamily": 1, "text": "Core Packages:\n- ArgoCD\n- Gitea\n- Ingress-nginx", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "Core Packages:\n- ArgoCD\n- Gitea\n- Ingress-nginx", "lineHeight": 1.25, "baseline": 93 }, { "type": "arrow", "version": 381, "versionNonce": 898794161, "isDeleted": false, "id": "nHmMkx97YgjINcsVC4VlS", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 820.0363651622429, "y": 721.0370993829702, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 364, "height": 609, "seed": 91164433, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [ { "type": "text", "id": "lvC-UeX1cG3atJnWyQWAR" } ], "updated": 1702423269710, "link": null, "locked": false, "startBinding": { "elementId": "-TheK_iiszzs08UFHds1X", "focus": 0.8139142814386041, "gap": 10.30000305175821 }, "endBinding": { "elementId": "rn5VxKirQVQTGadXpV6do", "focus": -0.7932071699015981, "gap": 18.798660584633126 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ 364, -201 ], [ 224, -609 ] ] }, { "type": "text", "version": 109, "versionNonce": 1849081503, "isDeleted": false, "id": "lvC-UeX1cG3atJnWyQWAR", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 2105.81969798695, "y": 499.03709938297015, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 222.43333435058594, "height": 70, "seed": 2075985137, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423259436, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "5. Sync Custom \nPackages", "textAlign": "center", "verticalAlign": "middle", "containerId": "nHmMkx97YgjINcsVC4VlS", "originalText": "5. Sync Custom Packages", "lineHeight": 1.25, "baseline": 60 }, { "type": "rectangle", "version": 209, "versionNonce": 628869823, "isDeleted": false, "id": "K1xk0WFzyBRPJQ1A3rvF9", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1092.763637889515, "y": 639.2189175647882, "strokeColor": "#1971c2", "backgroundColor": "transparent", "width": 321.00000000000017, "height": 207.99999999999994, "seed": 1150369489, "groupIds": [ "fqu4sqeMOTfqdQqVK5MTz" ], "frameId": null, "roundness": { "type": 3 }, "boundElements": [ { "id": "4AOkOmojUQrdiA36lQ8DU", "type": "arrow" } ], "updated": 1702423269501, "link": null, "locked": false }, { "type": "text", "version": 212, "versionNonce": 1797213112, "isDeleted": false, "id": "B1TLthmjZljTpu4TvrlaW", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1113.763637889515, "y": 653.2189175647882, "strokeColor": "#1971c2", "backgroundColor": "transparent", "width": 212.23333740234375, "height": 35, "seed": 1048788145, "groupIds": [ "fqu4sqeMOTfqdQqVK5MTz" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158954, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "Local Directory", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "Local Directory", "lineHeight": 1.25, "baseline": 25 }, { "type": "text", "version": 239, "versionNonce": 1377201096, "isDeleted": false, "id": "IF1D9aqYp7FoVsn6gx45t", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1124.763637889515, "y": 715.2189175647882, "strokeColor": "#1971c2", "backgroundColor": "transparent", "width": 238.06666564941406, "height": 105, "seed": 154828433, "groupIds": [ "fqu4sqeMOTfqdQqVK5MTz" ], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702500158954, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "contents:\n- argocd-app.yaml\n- manifest files", "textAlign": "left", "verticalAlign": "top", "containerId": null, "originalText": "contents:\n- argocd-app.yaml\n- manifest files", "lineHeight": 1.25, "baseline": 95 }, { "type": "arrow", "version": 313, "versionNonce": 1743014513, "isDeleted": false, "id": "4AOkOmojUQrdiA36lQ8DU", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 815.0363651622429, "y": 674.3529600675256, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 262.7272727272725, "height": 61.65717237957415, "seed": 1668187249, "groupIds": [], "frameId": null, "roundness": { "type": 2 }, "boundElements": [ { "type": "text", "id": "Lza-c0b-WjRNgd-m1X43U" } ], "updated": 1702423269710, "link": null, "locked": false, "startBinding": { "elementId": "-TheK_iiszzs08UFHds1X", "focus": -0.547290541551879, "gap": 5.30000305175821 }, "endBinding": { "elementId": "K1xk0WFzyBRPJQ1A3rvF9", "focus": -0.2398436923984328, "gap": 14.999999999999432 }, "lastCommittedPoint": null, "startArrowhead": null, "endArrowhead": "arrow", "points": [ [ 0, 0 ], [ 262.7272727272725, 61.65717237957415 ] ] }, { "type": "text", "version": 18, "versionNonce": 564588447, "isDeleted": false, "id": "Lza-c0b-WjRNgd-m1X43U", "fillStyle": "hachure", "strokeWidth": 1, "strokeStyle": "dashed", "roughness": 2, "opacity": 100, "angle": 0, "x": 1925.1500015258791, "y": 701.6815462573127, "strokeColor": "#e03131", "backgroundColor": "transparent", "width": 108.5, "height": 35, "seed": 1223085649, "groupIds": [], "frameId": null, "roundness": null, "boundElements": [], "updated": 1702423259439, "link": null, "locked": false, "fontSize": 28, "fontFamily": 1, "text": "4. Read", "textAlign": "center", "verticalAlign": "middle", "containerId": "4AOkOmojUQrdiA36lQ8DU", "originalText": "4. Read", "lineHeight": 1.25, "baseline": 25 } ], "appState": { "gridSize": null, "viewBackgroundColor": "#ffffff" }, "files": {} } ================================================ FILE: docs/minimum-requirements.md ================================================ # Minimum Requirements The requirements for your cluster will depend on what it is running but we recommend a minimum of 4 CPU cores and 4GiB of RAM. ================================================ FILE: docs/pluggable-packages.md ================================================ # Pluggable and configurable packaging proposal ## Background `idpbuilder` is a tool that aims to: - Allow developers to stand up a Kubernetes cluster with components that make up a Internal Developer Platform (IDP). - Allow for tests to run against IDPs in Continuous Integration systems. - Standup a working IDP for demo purposes. It also aims to achieve the above goals while having a single dependency, Docker, at run time. When implementing IDPs using open source projects, there is no one set of projects that fit the needs of all organizations because: 1. No organization went through the same path to reach the point of needing a IDP. 1. Past technology choices were made for specific needs of each organization. This results in organizationally unique technology inertia that may not be correctable in the near future. 1. No industry consensus and standards for choosing specific IDP components. To fit the needs from different organizations, idpbuilder needs to be flexible in the what and how it can deploy different packages. Currently idpbuilder uses ArgoCD to install a [set of application](https://github.com/cnoe-io/idpbuilder/blob/56089e4ae3b27cf90641bfbff2a96c36dd5263e1/pkg/apps/resources.go#L20-L32), and they cannot be changed without modifying the source code. In addition, the git server uses Go's embed capability to serve contents to ArgoCD. Because of this, to update package configurations in idpbuilder, it requires compiling the Go application. For Go developers this approach is straightforward to work with. For non-Go developers, this approach may be frustrating when needing to debug errors from an unfamiliar language while compiling the program. ## Goals The proposal in this document should: 1. Make the packages installed by `idpbuilder` configurable. 1. Minimize the number of runtime dependencies necessary. 1. Define an easy way to declare the packages to be installed. 1. Allow for fast local development feedback loop. ## Proposal This document proposes the following: - Make ArgoCD a hard requirement for now. - Define packages as Argo CD Applications (Helm, Kustomize, and raw manifests) - Use a more configurable Git server, Gitea. - Imperative pipelines for configuring packages are handled with ArgoCD resource hooks. In this implementation, we will make ArgoCD the technology of choice. However, we will strive to maintain separation between packages and specific CD technologies (Argo) to allow for future CD plug-ability. ![git](images/git.png) ### Essential Packages For `idpbuilder` to make the cluster ready to be used for non-essential packages, it must install: 1. In-cluster git server 2. ArgoCD 3. Ingress for git server and ArgoCD Once they are installed and ready, the manifests used should be pushed to an in-cluster git repository. The packages then can be managed by ArgoCD from that point. This allows for end users to make changes to them through GitOps by either using the Git UI or locally through Git pull / push. ### ArgoCD Currently, ArgoCD is a base requirement for both the AWS reference implementation and idpbuilder but not yet officially made a hard requirement. ArgoCD is the CD of choice for CNOE members and it should be the focus over other GitOps solutions. Packages then become the formats that ArgoCD supports natively: Helm charts, Kustomize, and raw manifests. #### Support for imperative pipelines Regardless of how applications are delivered declaratively, custom scripts are often needed before, during, and after application syncing to ensure applications reach the desired state. idpbuilder needs to provide a way to run custom scripts in a defined order. We could define a spec to support such cases, but considering the main use cases of idpbuilder center around everything being local, it doesn't require overly complex tasks. For example, in the reference implementation for AWS, the majority of scripting are done to manage authentication mechanisms. Another task that the scripts do is domain name configuration for each package such as setting the `baseUrl` field in the Backstage configuration file. In local environments, tasks like these are likely unnecessary because authentication is not necessary and domain names are predictable. ArgoCD supports resource hooks which allow users to define tasks to be run during application syncing. While there are some limitations to what it can do, for the majority of simple tasks resource hooks should suffice. ### The in-cluster git server The primary purpose of the in-cluster git server is to sync local files to it, then make them available for ArgoCD to use. As documented in [this issue](https://github.com/cnoe-io/idpbuilder/issues/32), using `gitea` offers more configurable and user friendly experience. In short, using it enables: - Git UI and ssh access for end users. - More configurable git server. - Include the source control system as a core component for a developer platform. - Move the outdated git dependency to a more modern and actively supported dependency. `gittea` offers installation into Kubernetes cluster using a helm chart. It should be leveraged to install it to the local cluster. The ideal way to install this would be to use ArgoCD. However, ArgoCD requires a Git server to read Helm values from. It is possible to host the values file on a public repository, but the idpbuilder core components should avoid depending on external systems. In secured environments, it may be impossible for ArgoCD to reach the public repository. It should follow the same pattern of installing ArgoCD by embedding them in the application binary. The manifests should be rendered at build time by using the `helm template` command with values checked into the repository. In case the embedded configuration does not work for some reason, we should provide a flag, `--git-manifest-file`. When used, it specifies a single file that contains manifests necessary to configure a git server. It is important to note that the file contains raw manifests that will be applied as-is, not helm values. Supporting manifest rendering mechanisms come with a cost of needing to include and maintain libraries and light logic to render these manifests. One of the goals of this proposal is to minimize dependencies. It's also difficult to ensure rendered manifests are what users intended to use. Users may have different versions of helm from our version. This may cause slight differences in manifests due to a bug or a feature differences. Users are expected to run the `helm template` command to generate manifests. ### Runtime Git server content generation As mentioned earlier, Git server contents are generated at compile time and cannot be changed at run time. To solve this, Git content should be created at run time by introducing a new flag, `--package`, to idpbuilder. This flag takes a directory that contains ArgoCD Applications. If this flag is not specified, use the embedded FS to provide the "default experience" where it uses the manifests provided at compile time to bootstrap and add predetermined packages to the cluster. Because Helm and Kustomize can reference remote repositories, this approach introduces a use case where secrets must be passed to the cluster from local machine. Kubernetes resource YAML files are often stored on a private Git server and require credentials to access. For ArgoCD to access the Git server, the credentials must be passed to ArgoCD as Kubernetes Secrets. To accomplish this, idpbuilder will provide a flag to pass secrets and other ArgoCD configuration options. `--argocd-config` flag should point to a directory with manifests for configuring ArgoCD, ConfigMaps and Secrets. These manifests will be applied after ArgoCD is deployed and ready. An example directory contents are shown below. ```yaml # --argocd-config ./configs apiVersion: v1 kind: Secret metadata: name: argo-helm namespace: argocd labels: argocd.argoproj.io/secret-type: repository stringData: name: argo url: https://argoproj.github.io/argo-helm type: helm username: my-username password: my-password --- apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm namespace: argocd labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd data: url: https://argo-cd-demo.argoproj.io ``` #### Local file handling To allow for faster feedback loop when developing Kubernetes applications and manifests, idpbuilder should support pushing local files to the in-cluster git repository if sources are specified using `files://`. Given the following application: ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application spec: sources: - path: argo-workflows repoURL: "files://test-package" targetRevision: HEAD ``` idpbuilder must: * Take and validate all manifests under the `test-package` directory. * Create a new repository in the in-cluster git server. * Push the files to the repository. * Replace `files://` with `https://git-server.git.svc.cluster.local` ## Future improvements - Extend support for using different tools for CD and imperative workflows. For example, we may consider supporting Tekton or Flagger for running imperative workflows. - Extend support for other GitOps solutions such as Flux CD. - Add support for authentication. As use cases grow, it will be necessary to support authentication mechanisms. Example use cases: GitHub credentials for ArgoCD, AWS credentials to pull images from a ECR registry. - Add support for capturing Kubernetes job outputs that were launched by ArgoCD Resource Hooks. Stdout and stderr are not saved for completed jobs by default. This will help debug problems when running imperative commands in Kubernetes Jobs. - Support for ArgoCD App of Apps. An App of Apps is an ArgoCD application that contains other ArgoCD applications. Support for this would require: - Rendering Helm charts and Kustomize. - Sync repository contents, then parse and replace URLs as described above. ## Alternatives Considered #### Use OCI images as applications Projects such as Sealer and Kapp aim to use OCI images as the artifact to define and deploy multiple Kubernetes resources. This has a few advantages. - Immutable single artifact that can be used to deploy to different clusters. - Simplicity. Application dependencies and supporting resources are defined and confined in the image. - Can use standard Kubernetes YAML files, Helm Charts, and Kustomize. - Native support for signing and verification through industry standard tools like cosign. In addition, both tools support applying changes in particular order. For example, you can run a Kubernetes Job to migrate database schema before rolling out a new image. Since many of the goals are covered by both projects, it is possible to incorporate some of their tools and libraries to implement our goals. While this approach addresses most of our goals, there are drawbacks. Firstly, it introduces a new layer for end users to debug. For end users to debug an issue related to Kubernetes manifest rendering, they now need to: 1. Figure out which OCI image contains the package with the problem. The problem may reside in one of dependent OCI images. 2. Extract the contents of the OCI image. Determine which one file is responsible for the issue. 3. Correct the issue. 4. Publish a new image. Secondly, these tools and using OCI images as packages are not well adopted by CNOE members as evidenced by the tech radar. idpbuilder should be useful and relevant to CNOE members. #### Define specs for imperative work To support use cases where more complex steps are needed to orchestrate different services in to the cluster, idpbuilder could define a configuration spec where end users can define their own steps. For example, a spec may look something like the following. ```yaml apiVersion: idpbuilder.cnoe.io/v1alpha1 kind: Config metadata: name: test spec: packages: - name: crossplane preCreation: - name: job1 secretRef: name: job1 path: ./secret1 type: helm chart: values: ./values.yaml url: "https://somewhere.cnoe.io/charts" spec: apiVersion: batch/v1 kind: Job metadata: name: pi postCreation: ... ``` This introduces a few problems. 1. Complexity. This introduces a completely new mechanisms to manage applications. Current idpbuilder design is very simple with no concept of pipelining. It allows end users to define manifests at compile time, and apply them as Argo CD applications. Introducing this feature and maintaining it may involve significant time commitment. 2. Yet another configuration format. With the explosion of Kubernetes based projects, a large number of configuration formats were created. Developers and operators are already needing to write and manage configuration files that look similar but slightly different. 3. No clear needs for task orchestration capabilities. We have so far not had a request for this capability with concrete needs and investing time and effort to implement and maintain this feature doesn't work. #### Git Repository Mirroring Another approach is to mirror contents from repositories using credentials from local machine, then push them to the in-cluster git server. This does not require credentials to be replicated to the cluster. A few consideration for this approach: 1. Kustomize references to private remotes. kustomize can reference remote repositories: ```yaml # kustomization.yaml resources: - https://github.com/kubernetes-sigs/kustomize//examples/multibases?timeout=120&ref=v3.3.1 namePrefix: remote- ``` In this example, to ensure the local git server has everything ArgoCD needs, idpbuilder must: * Pull manifests from `github.com/kubernetes-sigs/kustomize` * Create a new repository in in-cluster git server. * Push contents to the in-cluster repository. * Replace `github.com` with `git-server.git.svc.cluster.local` 2. Helm subcharts from private repositories. Helm subcharts may look like ``` # Chart.yaml dependencies: - name: nginx version: "1.2.3" repository: "https://example.com/charts" ``` In this example, idpbuilder must: * Pull `chart.tgz` for the nginx chart. * Push it to a in-cluster http server. * Replace `example.com` with `http-endpoint.git.svc.cluster.local` Given the complexity involved with this approach, the first iteration should focus on passing secrets to ArgoCD. When concrete use cases arise, approaches similar to this should be considered. ###### ArgoCD Application handling Consider a case where idpbuilder is given the flag `--package ./packages`, and the `packages` directory contains a yaml file for a ArgoCD application. ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application spec: sources: - chart: argo-workflows repoURL: https://argoproj.github.io/argo-helm targetRevision: 0.31.0 helm: releaseName: argo-workflows valueFiles: - $values/packages/argo-workflows/dev/values.yaml - repoURL: https://github.com/cnoe-io/argo-helm targetRevision: HEAD ref: values ``` In the above file, it instructs ArgoCD to use the charts from `argoproj.github.io/argo-helm` and use values stored at `https://github.com/cnoe-io/argo-helm/packages/argo-workflows/dev/values.yaml` In this case, idpbuilder must: * Replace `argoproj.github.io` with `http-endpoint.git.svc.cluster.local`. * Replace `github.com` with `git-server.git.svc.cluster.local`. ================================================ FILE: docs/private-registries.md ================================================ # Private registry authentication idpbuilder can be configured to use private registry authentication from the host filesystem by using the `--registry-config` flag with the `create` command. By default this will look for a registry config file in the default podman and docker paths (see the help text for details). You can optionally specify a file by doing the following: `--registry-config=$HOME/path/to/auth.json` ================================================ FILE: globals/project.go ================================================ package globals import "fmt" const ( ProjectName string = "idpbuilder" NginxNamespace string = "ingress-nginx" ArgoCDNamespace string = "argocd" SelfSignedCertSecretName = "idpbuilder-cert" SelfSignedCertCMName = "idpbuilder-cert" SelfSignedCertCMKeyName = "ca.crt" DefaultSANWildcard = "*.cnoe.localtest.me" DefaultHostName = "cnoe.localtest.me" ) func GetProjectNamespace(name string) string { return fmt.Sprintf("%s-%s", ProjectName, name) } ================================================ FILE: go.mod ================================================ module github.com/cnoe-io/idpbuilder go 1.22.0 toolchain go1.24.7 require ( code.gitea.io/sdk/gitea v0.16.0 github.com/cnoe-io/argocd-api v0.0.0-20241031202925-3091d64cb3c4 github.com/docker/docker v25.0.6+incompatible github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-logr/logr v1.4.2 github.com/google/go-cmp v0.6.0 github.com/google/go-github/v61 v61.0.0 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 k8s.io/api v0.30.5 k8s.io/apiextensions-apiserver v0.30.5 k8s.io/apimachinery v0.30.5 k8s.io/cli-runtime v0.30.5 k8s.io/client-go v0.30.5 k8s.io/klog/v2 v2.120.1 sigs.k8s.io/controller-runtime v0.18.5 sigs.k8s.io/kind v0.29.0 sigs.k8s.io/kustomize/kyaml v0.16.0 sigs.k8s.io/yaml v1.4.0 ) require ( al.essio.dev/pkg/shellescape v1.5.1 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-version v1.5.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect golang.org/x/crypto v0.28.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) ================================================ FILE: go.sum ================================================ al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho= al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= code.gitea.io/sdk/gitea v0.16.0 h1:gAfssETO1Hv9QbE+/nhWu7EjoFQYKt6kPoyDytQgw00= code.gitea.io/sdk/gitea v0.16.0/go.mod h1:ndkDk99BnfiUCCYEUhpNzi0lpmApXlwRFqClBlOlEBg= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cnoe-io/argocd-api v0.0.0-20241031202925-3091d64cb3c4 h1:gjpMCcU3hPy1dShDW8bLGjUmIojB3Bn9rjZbAiBp5V0= github.com/cnoe-io/argocd-api v0.0.0-20241031202925-3091d64cb3c4/go.mod h1:qItVgtDzIzaRvo82IfN9Is9+cTBz6dVETxBftESVXoY= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go= github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hashicorp/go-version v1.5.0 h1:O293SZ2Eg+AAYijkVK3jR786Am1bhDEh2GHT0tIVE5E= github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.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 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/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.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= k8s.io/api v0.30.5 h1:Coz05sfEVywzGcA96AJPUfs2B8LBMnh+IIsM+HCfaz8= k8s.io/api v0.30.5/go.mod h1:HfNBGFvq9iNK8dmTKjYIdAtMxu8BXTb9c1SJyO6QjKs= k8s.io/apiextensions-apiserver v0.30.5 h1:JfXTIyzXf5+ryncbp7T/uaVjLdvkwtqoNG2vo7S2a6M= k8s.io/apiextensions-apiserver v0.30.5/go.mod h1:uVLEME2UPA6UN22i+jTu66B9/0CnsjlHkId+Awo0lvs= k8s.io/apimachinery v0.30.5 h1:CQZO19GFgw4zcOjY2H+mJ3k1u1o7zFACTNCB7nu4O18= k8s.io/apimachinery v0.30.5/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/cli-runtime v0.30.5 h1:MWY6efoBVH3h0O6p2DgaQszabV5ZntHZwTHBkiz+PSI= k8s.io/cli-runtime v0.30.5/go.mod h1:AKMWLDIJQUA5a7yEh5gmzkhpZqYpuDEVovanugfSnQk= k8s.io/client-go v0.30.5 h1:vEDSzfTz0F8TXcWVdXl+aqV7NAV8M3UvC2qnGTTCoKw= k8s.io/client-go v0.30.5/go.mod h1:/q5fHHBmhAUesOOFJACpD7VJ4e57rVtTPDOsvXrPpMk= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.18.5 h1:nTHio/W+Q4aBlQMgbnC5hZb4IjIidyrizMai9P6n4Rk= sigs.k8s.io/controller-runtime v0.18.5/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.29.0 h1:3TpCsyh908IkXXpcSnsMjWdwdWjIl7o9IMZImZCWFnI= sigs.k8s.io/kind v0.29.0/go.mod h1:ldWQisw2NYyM6k64o/tkZng/1qQW7OlzcN5a8geJX3o= sigs.k8s.io/kustomize/kyaml v0.16.0 h1:6J33uKSoATlKZH16unr2XOhDI+otoe2sR3M8PDzW3K0= sigs.k8s.io/kustomize/kyaml v0.16.0/go.mod h1:xOK/7i+vmE14N2FdFyugIshB8eF6ALpy7jI87Q2nRh4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= ================================================ FILE: hack/argo-cd/argocd-application-controller.yaml ================================================ apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller spec: template: spec: containers: - name: argocd-application-controller imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/argocd-applicationset-controller.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: template: spec: containers: - name: argocd-applicationset-controller imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/argocd-cm.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm data: application.resourceTrackingMethod: annotation accounts.developer: apiKey, login timeout.reconciliation: 60s resource.exclusions: | - kinds: - ProviderConfigUsage apiGroups: - "*" ================================================ FILE: hack/argo-cd/argocd-rbac-dev.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: argocd-rbac-cm data: policy.csv: | p, role:developer, applications, *, *, allow g, developer, role:developer ================================================ FILE: hack/argo-cd/argocd-redis.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: template: spec: containers: - name: redis imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/argocd-repo-server.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: template: spec: containers: - name: argocd-repo-server imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/argocd-server.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-server template: metadata: labels: app.kubernetes.io/name: argocd-server spec: containers: - args: - /usr/local/bin/argocd-server - "{{if .UsePathRouting}}" - --insecure - --basehref - /argocd - "{{end}}" name: argocd-server imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/argocd-tls-certs-cm.yaml.tmpl ================================================ apiVersion: v1 kind: ConfigMap metadata: name: argocd-tls-certs-cm labels: app.kubernetes.io/name: argocd-tls-certs-cm app.kubernetes.io/part-of: argocd data: 'gitea.{{.Host}}': | {{ .SelfSignedCert | indentNewLines 4 }} '{{.Host}}': | {{ .SelfSignedCert | indentNewLines 4 }} ================================================ FILE: hack/argo-cd/dex-server.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: argocd-dex-server spec: replicas: 0 template: spec: containers: - name: dex imagePullPolicy: IfNotPresent initContainers: - name: copyutil imagePullPolicy: IfNotPresent ================================================ FILE: hack/argo-cd/generate-manifests.sh ================================================ #!/bin/bash INSTALL_YAML="pkg/controllers/localbuild/resources/argo/install.yaml" INGRESS_YAML="pkg/controllers/localbuild/resources/argo/ingress.yaml" echo "# UCP ARGO INSTALL RESOURCES" > ${INSTALL_YAML} echo "# This file is auto-generated with 'hack/argo-cd/generate-manifests.sh'" >> ${INSTALL_YAML} kustomize build ./hack/argo-cd/ >> ${INSTALL_YAML} cat ./hack/argo-cd/ingress.yaml.tmpl > ${INGRESS_YAML} ================================================ FILE: hack/argo-cd/ingress.yaml.tmpl ================================================ {{- if .UsePathRouting -}} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-server-ingress-http namespace: argocd annotations: nginx.ingress.kubernetes.io/backend-protocol: "HTTP" nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - path: /argocd(/|$)(.*) pathType: ImplementationSpecific backend: service: name: argocd-server port: name: http {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - path: /argocd(/|$)(.*) pathType: ImplementationSpecific backend: service: name: argocd-server port: name: http {{ end }} {{- else -}} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-server-ingress namespace: argocd annotations: nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/ssl-passthrough: "true" spec: ingressClassName: "nginx" rules: - host: argocd.{{ .IngressHost }} http: paths: - path: / pathType: Prefix backend: service: name: argocd-server port: name: https {{- if ne .IngressHost .Host }} - host: argocd.{{ .Host }} http: paths: - path: / pathType: Prefix backend: service: name: argocd-server port: name: https {{ end }} {{ end }} ================================================ FILE: hack/argo-cd/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://raw.githubusercontent.com/argoproj/argo-cd/v3.1.7/manifests/install.yaml patches: - path: dex-server.yaml - path: notifications-controller.yaml - path: argocd-cm.yaml - path: argocd-server.yaml - path: argocd-application-controller.yaml - path: argocd-applicationset-controller.yaml - path: argocd-repo-server.yaml - path: argocd-redis.yaml - path: argocd-tls-certs-cm.yaml.tmpl - path: argocd-rbac-dev.yaml ================================================ FILE: hack/argo-cd/notifications-controller.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: argocd-notifications-controller spec: replicas: 0 template: spec: containers: - name: argocd-notifications-controller imagePullPolicy: IfNotPresent ================================================ FILE: hack/boilerplate.go.txt ================================================ /* Copyright 2023. 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. */ ================================================ FILE: hack/embedded-resources.sh ================================================ #!/bin/bash DIRECTORIES='argo-cd gitea ingress-nginx' for dir in $DIRECTORIES; do ./hack/$dir/generate-manifests.sh; if [[ $? -ne 0 ]]; then echo "error running script: ./hack/$dir/generate-manifests.sh" exit 1 fi done ================================================ FILE: hack/gitea/generate-manifests.sh ================================================ #!/bin/bash set -e INSTALL_YAML="pkg/controllers/localbuild/resources/gitea/k8s/install.yaml" GITEA_DIR="./hack/gitea" CHART_VERSION="12.1.2" echo "# GITEA INSTALL RESOURCES" >${INSTALL_YAML} echo "# This file is auto-generated with 'hack/gitea/generate-manifests.sh'" >>${INSTALL_YAML} helm repo add gitea-charts --force-update https://dl.gitea.com/charts/ helm repo update helm template my-gitea gitea-charts/gitea -f ${GITEA_DIR}/values.yaml --version ${CHART_VERSION} >>${INSTALL_YAML} sed -i.bak '3d' ${INSTALL_YAML} # helm template for pvc uses Release.namespace which doesn't get set # when running the helm "template" command # See: https://gitea.com/gitea/helm-chart/issues/630 # and: https://gitea.com/gitea/helm-chart/src/commit/3b2b700441e91a19a535e05de3a9eab2fef0b117/templates/gitea/pvc.yaml#L6 # and: https://github.com/helm/helm/issues/3553#issuecomment-1186518158 # and: https://github.com/splunk/splunk-connect-for-kubernetes/pull/790 sed -i.bak 's/namespace: default/namespace: gitea/g' ${INSTALL_YAML} cat ${GITEA_DIR}/ingress.yaml.tmpl >>${INSTALL_YAML} rm -rf "${INSTALL_YAML}.bak" ================================================ FILE: hack/gitea/ingress.yaml.tmpl ================================================ {{- if .UsePathRouting }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path-oci-root namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2 pathType: Prefix {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2 pathType: Prefix {{ end }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path-oci-repo namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /v2/$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2/gitea(/|$)(.*) pathType: ImplementationSpecific {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2/gitea(/|$)(.*) pathType: ImplementationSpecific {{ end }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /gitea(/|$)(.*) pathType: ImplementationSpecific {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /gitea(/|$)(.*) pathType: ImplementationSpecific {{ end }} {{ else }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-custom namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m spec: ingressClassName: nginx rules: - host: gitea.{{ .IngressHost }} http: paths: - path: / pathType: Prefix backend: service: name: my-gitea-http port: number: 3000 {{- if ne .IngressHost .Host }} - host: gitea.{{ .Host }} http: paths: - path: / pathType: Prefix backend: service: name: my-gitea-http port: number: 3000 {{ end }} {{ end }} ================================================ FILE: hack/gitea/values.yaml ================================================ valkey-cluster: enabled: false postgresql: enabled: false postgresql-ha: enabled: false persistence: enabled: true size: 5Gi test: enabled: false gitea: admin: existingSecret: gitea-credential config: database: DB_TYPE: sqlite3 session: PROVIDER: memory cache: ADAPTER: memory queue: TYPE: level server: DOMAIN: '{{- if .UsePathRouting -}} {{ .Host }} {{- else -}} gitea.{{- .Host }} {{- end }}' ROOT_URL: '{{- if .UsePathRouting }} {{- .Protocol }}://{{ .Host }}:{{ .Port }}/gitea {{- else }} {{- .Protocol }}://gitea.{{ .Host }}:{{ .Port }} {{- end }}' SSH_PORT: 32222 SSH_LISTEN_PORT: 2222 webhook: ALLOWED_HOST_LIST: private SKIP_TLS_VERIFY: true service: http: type: NodePort port: 3000 nodePort: 32223 externalTrafficPolicy: Local ssh: type: NodePort port: 32222 nodePort: 32222 externalTrafficPolicy: Local ingress: # NOTE: The ingress is generated in a later step for path based routing feature See: hack/argo-cd/generate-manifests.sh enabled: false image: pullPolicy: "IfNotPresent" # Adds -rootless suffix to image name rootless: true ================================================ FILE: hack/ingress-nginx/cm-ingress-nginx-controller.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: ingress-nginx-controller namespace: ingress-nginx data: allow-snippet-annotations: "true" proxy-buffer-size: "32k" proxy-busy-buffers-size: "32k" use-forwarded-headers: "true" ================================================ FILE: hack/ingress-nginx/deployment-ingress-nginx.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 spec: terminationGracePeriodSeconds: 0 containers: - name: controller args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key - --watch-ingress-without-class=true - --publish-status-address=localhost - --enable-ssl-passthrough - --default-ssl-certificate=ingress-nginx/idpbuilder-cert ports: - containerPort: 80 hostPort: 80 name: http protocol: TCP - containerPort: 443 hostPort: 443 name: https protocol: TCP ================================================ FILE: hack/ingress-nginx/generate-manifests.sh ================================================ #!/bin/bash INSTALL_YAML="pkg/controllers/localbuild/resources/nginx/k8s/ingress-nginx.yaml" NGINX_DIR="./hack/ingress-nginx" echo "# INGRESS-NGINX INSTALL RESOURCES" > ${INSTALL_YAML} echo "# This file is auto-generated with 'hack/ingress-nginx/generate-manifests.sh'" >> ${INSTALL_YAML} kustomize build ${NGINX_DIR} >> ${INSTALL_YAML} cat ${NGINX_DIR}/service-ingress-nginx.yaml.tmpl >> ${INSTALL_YAML} ================================================ FILE: hack/ingress-nginx/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.0/deploy/static/provider/kind/deploy.yaml patches: - path: deployment-ingress-nginx.yaml - path: cm-ingress-nginx-controller.yaml - target: group: "" version: v1 kind: Service name: ingress-nginx-controller namespace: ingress-nginx patch: | $patch: delete kind: Kustomization metadata: name: ingress-nginx-controller # ArgoCD has poor support for ttlSecondsAfterFinished and it shouldn't be essential to clean these up - target: group: batch version: v1 kind: Job name: ingress-nginx-admission-create namespace: ingress-nginx patch: | - op: remove path: /spec/ttlSecondsAfterFinished - target: group: batch version: v1 kind: Job name: ingress-nginx-admission-patch namespace: ingress-nginx patch: | - op: remove path: /spec/ttlSecondsAfterFinished ================================================ FILE: hack/ingress-nginx/service-ingress-nginx.yaml.tmpl ================================================ --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: {{ .Protocol }} name: {{ .Protocol }}-{{ .Port }} port: {{ .Port }} protocol: TCP targetPort: {{ .Protocol }} - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort ================================================ FILE: hack/install.sh ================================================ #!/bin/bash set -e -o pipefail # get the latest stable release by look for tag name pattern like 'v*.*.*'. For example, v1.1.1 # GitHub API returns releases in chronological order so we take the first matching tag name. version=$(curl -s https://api.github.com/repos/cnoe-io/idpbuilder/releases | grep tag_name | grep -o -e '"v[0-9].[0-9].[0-9]"' | head -n1 | sed 's/"//g') echo "Downloading idpbuilder version ${version}" curl -L --progress-bar -o ./idpbuilder.tar.gz "https://github.com/cnoe-io/idpbuilder/releases/download/${version}/idpbuilder-$(uname | awk '{print tolower($0)}')-$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/').tar.gz" tar xzf idpbuilder.tar.gz echo "Moving idpbuilder binary to /usr/local/bin" sudo mv ./idpbuilder /usr/local/bin/ idpbuilder version echo "Successfully installed idpbuilder" ================================================ FILE: main.go ================================================ package main import ( "context" "fmt" "os" "os/signal" "syscall" "github.com/cnoe-io/idpbuilder/pkg/cmd" ) func main() { interrupted := make(chan os.Signal, 1) defer close(interrupted) signal.Notify(interrupted, os.Interrupt, syscall.SIGTERM) defer signal.Stop(interrupted) ctx, cancel := context.WithCancelCause(context.Background()) go func() { select { case <-interrupted: cancel(fmt.Errorf("command interrupted")) } }() cmd.Execute(ctx) } ================================================ FILE: pkg/build/build.go ================================================ package build import ( "context" "fmt" "os" "slices" "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/controllers" "github.com/cnoe-io/idpbuilder/pkg/kind" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics/server" ) var ( setupLog = ctrl.Log.WithName("setup") ) type Build struct { name string cfg v1alpha1.BuildCustomizationSpec kindConfigPath string kubeConfigPath string kubeVersion string extraPortsMapping string registryConfig []string customPackageFiles []string customPackageDirs []string customPackageUrls []string packageCustomization map[string]v1alpha1.PackageCustomization exitOnSync bool scheme *runtime.Scheme CancelFunc context.CancelFunc } type NewBuildOptions struct { Name string TemplateData v1alpha1.BuildCustomizationSpec KindConfigPath string KubeConfigPath string KubeVersion string ExtraPortsMapping string RegistryConfig []string CustomPackageFiles []string CustomPackageDirs []string CustomPackageUrls []string PackageCustomization map[string]v1alpha1.PackageCustomization ExitOnSync bool Scheme *runtime.Scheme CancelFunc context.CancelFunc } func NewBuild(opts NewBuildOptions) *Build { return &Build{ name: opts.Name, kindConfigPath: opts.KindConfigPath, kubeConfigPath: opts.KubeConfigPath, kubeVersion: opts.KubeVersion, extraPortsMapping: opts.ExtraPortsMapping, registryConfig: opts.RegistryConfig, customPackageFiles: opts.CustomPackageFiles, customPackageDirs: opts.CustomPackageDirs, customPackageUrls: opts.CustomPackageUrls, packageCustomization: opts.PackageCustomization, exitOnSync: opts.ExitOnSync, scheme: opts.Scheme, cfg: opts.TemplateData, CancelFunc: opts.CancelFunc, } } func (b *Build) ReconcileKindCluster(ctx context.Context, recreateCluster bool) error { // Initialize Kind Cluster cluster, err := kind.NewCluster(b.name, b.kubeVersion, b.kubeConfigPath, b.kindConfigPath, b.extraPortsMapping, b.registryConfig, b.cfg, setupLog) if err != nil { setupLog.Error(err, "Error Creating kind cluster") return err } // Build Kind cluster if err := cluster.Reconcile(ctx, recreateCluster); err != nil { setupLog.Error(err, "Error starting kind cluster") return err } // Create Kube Config for Kind cluster if err := cluster.ExportKubeConfig(b.name, false); err != nil { setupLog.Error(err, "Error exporting kubeconfig from kind cluster") return err } return nil } func (b *Build) GetKubeConfig() (*rest.Config, error) { kubeConfig, err := clientcmd.BuildConfigFromFlags("", b.kubeConfigPath) if err != nil { setupLog.Error(err, "Error building kubeconfig from kind cluster") return nil, err } return kubeConfig, nil } func (b *Build) GetKubeClient(kubeConfig *rest.Config) (client.Client, error) { kubeClient, err := client.New(kubeConfig, client.Options{Scheme: b.scheme}) if err != nil { setupLog.Error(err, "Error creating kubernetes client") return nil, err } return kubeClient, nil } func (b *Build) ReconcileCRDs(ctx context.Context, kubeClient client.Client) error { // Ensure idpbuilder CRDs if err := controllers.EnsureCRDs(ctx, b.scheme, kubeClient, b.cfg); err != nil { setupLog.Error(err, "Error creating idpbuilder CRDs") return err } return nil } func (b *Build) RunControllers(ctx context.Context, mgr manager.Manager, exitCh chan error, tmpDir string) error { return controllers.RunControllers(ctx, mgr, exitCh, b.CancelFunc, b.exitOnSync, b.cfg, tmpDir) } func (b *Build) isCompatible(ctx context.Context, kubeClient client.Client) (bool, error) { localBuild := v1alpha1.Localbuild{ ObjectMeta: metav1.ObjectMeta{ Name: b.name, }, } err := kubeClient.Get(ctx, client.ObjectKeyFromObject(&localBuild), &localBuild) if err != nil { if k8serrors.IsNotFound(err) { return true, nil } return false, err } ok := isBuildCustomizationSpecEqual(b.cfg, localBuild.Spec.BuildCustomization) if ok { return ok, nil } existing, given := localBuild.Spec.BuildCustomization, b.cfg existing.SelfSignedCert = "" given.SelfSignedCert = "" return false, fmt.Errorf("provided command flags and existing configurations are incompatible. please recreate the cluster. "+ "existing: %+v, given: %+v", existing, given) } func (b *Build) Run(ctx context.Context, recreateCluster bool) error { setupLog.Info("Creating kind cluster") if err := b.ReconcileKindCluster(ctx, recreateCluster); err != nil { return err } setupLog.V(1).Info("Getting Kube config") kubeConfig, err := b.GetKubeConfig() if err != nil { return err } setupLog.V(1).Info("Getting Kube client") kubeClient, err := b.GetKubeClient(kubeConfig) if err != nil { return err } setupLog.Info("Adding CRDs to the cluster") if err := b.ReconcileCRDs(ctx, kubeClient); err != nil { return err } setupLog.V(1).Info("Creating controller manager") // Create controller manager mgr, err := ctrl.NewManager(kubeConfig, ctrl.Options{ Scheme: b.scheme, Metrics: server.Options{ BindAddress: "0", }, }) if err != nil { setupLog.Error(err, "Error creating controller manager") return err } dir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s-", globals.ProjectName, b.name)) if err != nil { setupLog.Error(err, "creating temp dir") return err } defer os.RemoveAll(dir) setupLog.V(1).Info("Created temp directory for cloning repositories", "dir", dir) setupLog.Info("Setting up CoreDNS") err = setupCoreDNS(ctx, kubeClient, b.scheme, b.cfg) if err != nil { return err } setupLog.Info("Setting up TLS certificate") cert, err := setupSelfSignedCertificate(ctx, setupLog, kubeClient, b.cfg) if err != nil { return err } b.cfg.SelfSignedCert = string(cert) setupLog.V(1).Info("Checking for incompatible options from a previous run") ok, err := b.isCompatible(ctx, kubeClient) if err != nil { setupLog.Error(err, "Error while checking incompatible flags") return err } if !ok { return err } managerExit := make(chan error) setupLog.V(1).Info("Running controllers") if err := b.RunControllers(ctx, mgr, managerExit, dir); err != nil { setupLog.Error(err, "Error running controllers") return err } localBuild := v1alpha1.Localbuild{ ObjectMeta: metav1.ObjectMeta{ Name: b.name, }, } cliStartTime := time.Now().Format(time.RFC3339Nano) setupLog.Info("Creating localbuild resource") _, err = controllerutil.CreateOrUpdate(ctx, kubeClient, &localBuild, func() error { if localBuild.ObjectMeta.Annotations == nil { localBuild.ObjectMeta.Annotations = map[string]string{} } localBuild.ObjectMeta.Annotations[v1alpha1.CliStartTimeAnnotation] = cliStartTime localBuild.Spec = v1alpha1.LocalbuildSpec{ BuildCustomization: b.cfg, PackageConfigs: v1alpha1.PackageConfigsSpec{ Argo: v1alpha1.ArgoPackageConfigSpec{ Enabled: true, }, EmbeddedArgoApplications: v1alpha1.EmbeddedArgoApplicationsPackageConfigSpec{ Enabled: true, }, CustomPackageDirs: b.customPackageDirs, CustomPackageFiles: b.customPackageFiles, CustomPackageUrls: b.customPackageUrls, CorePackageCustomization: b.packageCustomization, }, } return nil }) if err != nil { return fmt.Errorf("creating localbuild resource: %w", err) } select { case mgrErr := <-managerExit: if mgrErr != nil { return mgrErr } case <-ctx.Done(): return nil } return nil } func isBuildCustomizationSpecEqual(s1, s2 v1alpha1.BuildCustomizationSpec) bool { // probably ok to use cmp.Equal but keeping it simple for now return s1.Protocol == s2.Protocol && s1.Host == s2.Host && s1.IngressHost == s2.IngressHost && s1.Port == s2.Port && s1.UsePathRouting == s2.UsePathRouting && s1.SelfSignedCert == s2.SelfSignedCert && s1.StaticPassword == s2.StaticPassword && s1.InsecureRegistryMirrors == s2.InsecureRegistryMirrors && slices.Equal(s1.RegistryMirrors, s2.RegistryMirrors) } ================================================ FILE: pkg/build/build_test.go ================================================ package build import ( "context" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" ) func TestIsCompatible(t *testing.T) { cfg := v1alpha1.BuildCustomizationSpec{ Protocol: "http", Host: "cnoe.localtest.me", IngressHost: "string", Port: "8443", UsePathRouting: false, SelfSignedCert: "some-cert", } b := Build{ name: "test", cfg: cfg, } ctx := context.Background() fClient := new(fakeKubeClient) fClient.On("Get", ctx, client.ObjectKey{Name: "test"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1alpha1.Localbuild) arg.Spec.BuildCustomization = cfg }).Return(nil) ok, err := b.isCompatible(ctx, fClient) assert.NoError(t, err) fClient.AssertExpectations(t) require.True(t, ok) fClient = new(fakeKubeClient) fClient.On("Get", ctx, client.ObjectKey{Name: "test"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1alpha1.Localbuild) c := cfg c.Host = "not-right" arg.Spec.BuildCustomization = c }).Return(nil) ok, err = b.isCompatible(ctx, fClient) assert.Error(t, err) fClient.AssertExpectations(t) require.False(t, ok) fClient = new(fakeKubeClient) fClient.On("Get", ctx, client.ObjectKey{Name: "test"}, mock.Anything, mock.Anything). Return(k8serrors.NewNotFound(schema.GroupResource{}, "name")) ok, err = b.isCompatible(ctx, fClient) assert.NoError(t, err) fClient.AssertExpectations(t) require.True(t, ok) } ================================================ FILE: pkg/build/coredns.go ================================================ package build import ( "context" "embed" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/k8s" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) const ( coreDNSTemplatePath = "templates/coredns" ) //go:embed templates var templates embed.FS func setupCoreDNS(ctx context.Context, kubeClient client.Client, scheme *runtime.Scheme, templateData v1alpha1.BuildCustomizationSpec) error { checkCM := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "coredns-conf-default", Namespace: "kube-system", }, } err := kubeClient.Get(ctx, client.ObjectKeyFromObject(checkCM), checkCM) if err == nil { return nil } objs, err := k8s.BuildCustomizedObjects("", coreDNSTemplatePath, templates, scheme, templateData) if err != nil { return fmt.Errorf("rendering embedded coredns files: %w", err) } for i := range objs { obj := objs[i] switch t := obj.(type) { case *appsv1.Deployment: dep := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: t.Name, Namespace: t.Namespace, }, } _, err = controllerutil.CreateOrUpdate(ctx, kubeClient, dep, func() error { dep.Spec = t.Spec return nil }) if err != nil { return fmt.Errorf("creating/updating deployment: %w", err) } case *corev1.ConfigMap: cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: t.Name, Namespace: t.Namespace, }, } _, err = controllerutil.CreateOrUpdate(ctx, kubeClient, cm, func() error { cm.Data = t.Data return nil }) if err != nil { return fmt.Errorf("creating/updating configmap: %w", err) } } } return nil } ================================================ FILE: pkg/build/templates/coredns/cm-coredns-custom.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: coredns-conf-custom namespace: kube-system data: custom.conf: | # insert custom rules here ================================================ FILE: pkg/build/templates/coredns/cm-coredns-default.yaml.tmpl ================================================ apiVersion: v1 kind: ConfigMap metadata: name: coredns-conf-default namespace: kube-system data: default.conf: | # Goal: Rewrite rules for in-cluster access to a service: gitea, argocd, etc using the same FQDN as for external access # subdomain names e.g. gitea.cnoe.localtest.me resolves to the IP address of the kubernetes ingress service and then will become ingress-nginx-controller.ingress-nginx.svc.cluster.local rewrite stop { name regex (.*).{{ .Host }} ingress-nginx-controller.ingress-nginx.svc.cluster.local answer auto } # host name resolves to the IP address of the kubernetes ingress service rewrite name exact {{ .Host }} ingress-nginx-controller.ingress-nginx.svc.cluster.local ================================================ FILE: pkg/build/templates/coredns/cm-coredns.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system data: Corefile: | .:53 { errors health { lameduck 5s } ready import ../coredns-configs/*.conf kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf { max_concurrent 1000 } cache 30 loop reload loadbalance } ================================================ FILE: pkg/build/templates/coredns/deployment-coredns.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: kube-dns name: coredns namespace: kube-system spec: progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: kube-dns strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 1 type: RollingUpdate template: metadata: creationTimestamp: null labels: k8s-app: kube-dns spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: - kube-dns topologyKey: kubernetes.io/hostname weight: 100 containers: - args: - -conf - /etc/coredns/Corefile image: registry.k8s.io/coredns/coredns:v1.11.1 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 5 httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 name: coredns ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP - containerPort: 9153 name: metrics protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /ready port: 8181 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: limits: memory: 170Mi requests: cpu: 100m memory: 70Mi securityContext: allowPrivilegeEscalation: false capabilities: add: - NET_BIND_SERVICE drop: - ALL readOnlyRootFilesystem: true terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /etc/coredns name: config-volume readOnly: true - mountPath: /etc/coredns-configs name: custom-configs readOnly: true dnsPolicy: Default nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: coredns serviceAccountName: coredns terminationGracePeriodSeconds: 30 tolerations: - key: CriticalAddonsOnly operator: Exists - effect: NoSchedule key: node-role.kubernetes.io/control-plane volumes: - configMap: defaultMode: 420 items: - key: Corefile path: Corefile name: coredns name: config-volume - name: custom-configs projected: sources: - configMap: name: coredns-conf-custom - configMap: name: coredns-conf-default ================================================ FILE: pkg/build/tls.go ================================================ package build import ( "bytes" "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "fmt" "io" "math/big" "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( certificateOrgName = "cnoe.io" certificateValidLength = time.Hour * 8766 argocdTLSSecretName = "argocd-server-tls" ) func createCertificateAndKeySecret(ctx context.Context, kubeClient client.Client, name, namespace string, cert, key []byte) error { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Type: corev1.SecretTypeTLS, Data: map[string][]byte{ corev1.TLSCertKey: cert, corev1.TLSPrivateKeyKey: key, }, } err := kubeClient.Create(ctx, secret) if err != nil { if k8serrors.IsAlreadyExists(err) { return nil } return err } return nil } func createIngressCertificateSecret(ctx context.Context, kubeClient client.Client, cert []byte) error { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: globals.SelfSignedCertCMName, Namespace: corev1.NamespaceDefault, }, Data: map[string][]byte{ globals.SelfSignedCertCMKeyName: cert, }, } err := kubeClient.Create(ctx, secret) if err != nil { if k8serrors.IsAlreadyExists(err) { return nil } return fmt.Errorf("creating configmap for certificate: %w", err) } return nil } func getIngressCertificateAndKey(ctx context.Context, kubeClient client.Client, name, namespace string) ([]byte, []byte, error) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Type: corev1.SecretTypeTLS, } err := kubeClient.Get(ctx, client.ObjectKeyFromObject(secret), secret) if err != nil { return nil, nil, err } cert, ok := secret.Data[corev1.TLSCertKey] if !ok { return nil, nil, fmt.Errorf("key %s not found in secret %s", corev1.TLSCertKey, name) } privateKey, ok := secret.Data[corev1.TLSPrivateKeyKey] if !ok { return nil, nil, fmt.Errorf("key %s not found in secret %s", corev1.TLSPrivateKeyKey, name) } return cert, privateKey, nil } func getOrCreateIngressCertificateAndKey(ctx context.Context, kubeClient client.Client, name, namespace string, sans []string) ([]byte, []byte, error) { c, p, err := getIngressCertificateAndKey(ctx, kubeClient, name, namespace) if err != nil { if k8serrors.IsNotFound(err) { cert, privateKey, cErr := createSelfSignedCertificate(sans) if cErr != nil { return nil, nil, cErr } cErr = createCertificateAndKeySecret(ctx, kubeClient, name, namespace, cert, privateKey) if cErr != nil { return nil, nil, fmt.Errorf("creating secret %s: %w", name, err) } return cert, privateKey, nil } else { return nil, nil, fmt.Errorf("getting secret %s: %w", name, err) } } return c, p, nil } func createSelfSignedCertificate(sans []string) ([]byte, []byte, error) { privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, nil, fmt.Errorf("generating private key: %w", err) } keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign notBefore := time.Now() notAfter := notBefore.Add(certificateValidLength) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return nil, nil, fmt.Errorf("generating certificate serial number: %w", err) } cert := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{certificateOrgName}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: keyUsage, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, IsCA: true, DNSNames: sans, } certBytes, err := x509.CreateCertificate(rand.Reader, &cert, &cert, &privateKey.PublicKey, privateKey) if err != nil { return nil, nil, fmt.Errorf("creating certificate: %w", err) } var certB bytes.Buffer var keyB bytes.Buffer err = pem.Encode(io.Writer(&certB), &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) if err != nil { return nil, nil, fmt.Errorf("encoding cert: %w", err) } certOut, err := io.ReadAll(&certB) if err != nil { return nil, nil, fmt.Errorf("reading buffer: %w", err) } privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) if err != nil { return nil, nil, fmt.Errorf("marshal private key: %w", err) } err = pem.Encode(io.Writer(&keyB), &pem.Block{Type: "PRIVATE KEY", Bytes: privateKeyBytes}) if err != nil { return nil, nil, fmt.Errorf("encoding private key: %w", err) } privateKeyOut, err := io.ReadAll(&keyB) if err != nil { return nil, nil, fmt.Errorf("reading buffer: %w", err) } return certOut, privateKeyOut, nil } func setupSelfSignedCertificate(ctx context.Context, logger logr.Logger, kubeclient client.Client, config v1alpha1.BuildCustomizationSpec) ([]byte, error) { if err := k8s.EnsureNamespace(ctx, kubeclient, globals.NginxNamespace); err != nil { return nil, err } if err := k8s.EnsureNamespace(ctx, kubeclient, globals.ArgoCDNamespace); err != nil { return nil, err } sans := []string{ globals.DefaultHostName, globals.DefaultSANWildcard, } if config.Host != globals.DefaultHostName { sans = []string{ config.Host, fmt.Sprintf("*.%s", config.Host), } } if config.IngressHost != config.Host { sans = append(sans, config.IngressHost, fmt.Sprintf("*.%s", config.IngressHost)) } logger.V(1).Info("Creating/getting certificate", "host", config.Host, "sans", sans) cert, privateKey, err := getOrCreateIngressCertificateAndKey(ctx, kubeclient, globals.SelfSignedCertSecretName, globals.NginxNamespace, sans) if err != nil { return nil, err } logger.V(1).Info("Creating secret for certificate", "host", config.Host) err = createIngressCertificateSecret(ctx, kubeclient, cert) if err != nil { return nil, err } logger.V(1).Info("Creating secret for ArgoCD server", "host", config.Host) err = createCertificateAndKeySecret(ctx, kubeclient, argocdTLSSecretName, globals.ArgoCDNamespace, cert, privateKey) if err != nil { return nil, err } return cert, nil } ================================================ FILE: pkg/build/tls_test.go ================================================ package build import ( "context" "crypto/tls" "crypto/x509" "encoding/pem" "testing" "github.com/cnoe-io/idpbuilder/globals" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" ) type fakeKubeClient struct { mock.Mock client.Client } func (f *fakeKubeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { args := f.Called(ctx, key, obj, opts) return args.Error(0) } func (f *fakeKubeClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { args := f.Called(ctx, obj, opts) return args.Error(0) } func TestCreateSelfSignedCertificate(t *testing.T) { sans := []string{"cnoe.io", "*.cnoe.io"} c, k, err := createSelfSignedCertificate(sans) assert.NoError(t, err) _, err = tls.X509KeyPair(c, k) assert.NoError(t, err) block, _ := pem.Decode(c) assert.Equal(t, "CERTIFICATE", block.Type) cert, err := x509.ParseCertificate(block.Bytes) assert.NoError(t, err) assert.Equal(t, 2, len(cert.DNSNames)) expected := map[string]struct{}{ "cnoe.io": {}, "*.cnoe.io": {}, } for _, s := range cert.DNSNames { _, ok := expected[s] if ok { delete(expected, s) } else { t.Fatalf("unexpected key %s found", s) } } assert.Equal(t, 0, len(expected)) } func TestGetOrCreateIngressCertificateAndKey(t *testing.T) { ctx := context.Background() fClient := new(fakeKubeClient) fClient.On("Get", ctx, client.ObjectKey{Name: globals.SelfSignedCertSecretName, Namespace: globals.NginxNamespace}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*corev1.Secret) d := map[string][]byte{ corev1.TLSPrivateKeyKey: []byte("abc"), corev1.TLSCertKey: []byte("abc"), } arg.Data = d }).Return(nil) _, _, err := getOrCreateIngressCertificateAndKey(ctx, fClient, globals.SelfSignedCertSecretName, globals.NginxNamespace, []string{globals.DefaultHostName, globals.DefaultSANWildcard}) assert.NoError(t, err) fClient.AssertExpectations(t) fClient = new(fakeKubeClient) fClient.On("Get", ctx, client.ObjectKey{Name: globals.SelfSignedCertSecretName, Namespace: globals.NginxNamespace}, mock.Anything, mock.Anything). Return(k8serrors.NewNotFound(schema.GroupResource{}, "name")) fClient.On("Create", ctx, mock.Anything, mock.Anything).Return(nil) c, k, err := getOrCreateIngressCertificateAndKey(ctx, fClient, globals.SelfSignedCertSecretName, globals.NginxNamespace, []string{globals.DefaultHostName, globals.DefaultSANWildcard}) assert.NoError(t, err) _, err = tls.X509KeyPair(c, k) assert.NoError(t, err) } ================================================ FILE: pkg/cmd/create/root.go ================================================ package create import ( "context" "fmt" "net/url" "os" "path/filepath" "strings" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/build" "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/spf13/cobra" "k8s.io/client-go/util/homedir" ) const ( recreateClusterUsage = "Delete cluster first if it already exists." buildNameUsage = "Name for build (Prefix for kind cluster name, pod names, etc)." devPasswordUsage = "Set the password \"developer\" for the admin user of the applications: argocd & gitea." kubeVersionUsage = "Version of the kind kubernetes cluster to create." extraPortsMappingUsage = "List of extra ports to expose on the docker container and kubernetes cluster as nodePort " + "(e.g. \"22:32222,9090:39090,etc\")." registryConfigUsage = "List of paths to mount as the registry config, uses the first one that exists" kindConfigPathUsage = "Path or URL to the kind config file to be used instead of the default." hostUsage = "Host name to access resources in this cluster." ingressHostUsage = "Host name used by ingresses. Useful when you have another proxy in front of ingress-nginx that idpbuilder provisions." protocolUsage = "Protocol to use to access web UIs. http or https." portUsage = "Port number to use to access web UIs." pathRoutingUsage = "When set to true, web UIs are exposed under single domain name. " + "e.g. \"https://cnoe.localtest.me/argocd\" instead of \"https://argocd.cnoe.localtest.me\"" extraPackagesUsage = "Paths to locations containing custom packages" packageCustomizationFilesUsage = "Name of the package and the path to file to customize the core packages with. " + "valid package names are: argocd, nginx, and gitea. e.g. argocd:/tmp/argocd.yaml" registryMirrorsUsage = "List of registry mirrors in format target=address (e.g. \"docker.io=http://kind-registry:5000,ghcr.io=http://kind-registry:5000\")" insecureRegistryMirrorsUsage = "When set, configure registry mirrors with insecure TLS verification (skip_verify = true)." noExitUsage = "When set, idpbuilder will not exit after all packages are synced. Useful for continuously syncing local directories." ) var ( // Flags recreateCluster bool buildName string devPassword bool kubeVersion string extraPortsMapping string kindConfigPath string extraPackages []string registryConfig []string registryMirrors []string insecureRegistryMirrors bool packageCustomizationFiles []string noExit bool protocol string host string ingressHost string port string pathRouting bool ) var CreateCmd = &cobra.Command{ Use: "create", Short: "(Re)Create an IDP cluster", Long: ``, RunE: create, PreRunE: preCreateE, SilenceUsage: true, } func init() { // cluster related flags CreateCmd.PersistentFlags().BoolVar(&recreateCluster, "recreate", false, recreateClusterUsage) CreateCmd.PersistentFlags().StringVar(&buildName, "build-name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().MarkDeprecated("build-name", "use --name instead.") CreateCmd.PersistentFlags().StringVar(&buildName, "name", "localdev", buildNameUsage) CreateCmd.PersistentFlags().BoolVar(&devPassword, "dev-password", false, devPasswordUsage) CreateCmd.PersistentFlags().StringVar(&kubeVersion, "kube-version", "v1.33.1", kubeVersionUsage) CreateCmd.PersistentFlags().StringVar(&extraPortsMapping, "extra-ports", "", extraPortsMappingUsage) CreateCmd.PersistentFlags().StringVar(&kindConfigPath, "kind-config", "", kindConfigPathUsage) CreateCmd.PersistentFlags().StringSliceVar(®istryConfig, "registry-config", []string{}, registryConfigUsage) CreateCmd.PersistentFlags().Lookup("registry-config").NoOptDefVal = "$XDG_RUNTIME_DIR/containers/auth.json,$HOME/.docker/config.json" CreateCmd.PersistentFlags().StringSliceVar(®istryMirrors, "registry-mirrors", []string{}, registryMirrorsUsage) CreateCmd.PersistentFlags().BoolVar(&insecureRegistryMirrors, "insecure-registry-mirrors", false, insecureRegistryMirrorsUsage) // in-cluster resources related flags CreateCmd.PersistentFlags().StringVar(&host, "host", globals.DefaultHostName, hostUsage) CreateCmd.PersistentFlags().StringVar(&ingressHost, "ingress-host-name", "", ingressHostUsage) CreateCmd.PersistentFlags().StringVar(&protocol, "protocol", "https", protocolUsage) CreateCmd.PersistentFlags().StringVar(&port, "port", "8443", portUsage) CreateCmd.PersistentFlags().BoolVar(&pathRouting, "use-path-routing", false, pathRoutingUsage) CreateCmd.Flags().StringSliceVarP(&extraPackages, "package", "p", []string{}, extraPackagesUsage) CreateCmd.Flags().StringSliceVarP(&packageCustomizationFiles, "package-custom-file", "c", []string{}, packageCustomizationFilesUsage) // idpbuilder related flags CreateCmd.Flags().BoolVarP(&noExit, "no-exit", "n", true, noExitUsage) } func preCreateE(cmd *cobra.Command, args []string) error { return helpers.SetLogger() } func create(cmd *cobra.Command, args []string) error { ctx, ctxCancel := context.WithCancel(cmd.Context()) defer ctxCancel() kubeConfigPath := filepath.Join(homedir.HomeDir(), ".kube", "config") protocol = strings.ToLower(protocol) host = strings.ToLower(host) if ingressHost == "" { ingressHost = host } err := validate() if err != nil { return err } var localFiles []string var localDirs []string var remotePaths []string if len(extraPackages) > 0 { r, f, d, pErr := helpers.ParsePackageStrings(extraPackages) if pErr != nil { return pErr } localFiles = f localDirs = d remotePaths = r } o := make(map[string]v1alpha1.PackageCustomization) for i := range packageCustomizationFiles { c, pErr := getPackageCustomFile(packageCustomizationFiles[i]) if pErr != nil { return pErr } o[c.Name] = c } parsedMirrors, err := parseRegistryMirrors(registryMirrors) if err != nil { return err } exitOnSync := true if cmd.Flags().Changed("no-exit") { exitOnSync = !noExit } // If registry-config is unset we pass nil // If registry-config is change (--registry-config=foo) we pass the new value // If registry-config is set but unchanged (--registry-confg) we pass "" maybeRegistryConfig := []string{} if cmd.Flags().Changed("registry-config") { maybeRegistryConfig = registryConfig } opts := build.NewBuildOptions{ Name: buildName, KubeVersion: kubeVersion, KubeConfigPath: kubeConfigPath, KindConfigPath: kindConfigPath, ExtraPortsMapping: extraPortsMapping, RegistryConfig: maybeRegistryConfig, TemplateData: v1alpha1.BuildCustomizationSpec{ Protocol: protocol, Host: host, IngressHost: ingressHost, Port: port, UsePathRouting: pathRouting, StaticPassword: devPassword, RegistryMirrors: parsedMirrors, InsecureRegistryMirrors: insecureRegistryMirrors, }, CustomPackageFiles: localFiles, CustomPackageDirs: localDirs, CustomPackageUrls: remotePaths, ExitOnSync: exitOnSync, PackageCustomization: o, Scheme: k8s.GetScheme(), CancelFunc: ctxCancel, } b := build.NewBuild(opts) if err := b.Run(ctx, recreateCluster); err != nil { return err } if cmd.Context().Err() != nil { return context.Cause(cmd.Context()) } printSuccessMsg() return nil } func validate() error { if buildName == "" { return fmt.Errorf("must specify build-name") } _, err := url.Parse(fmt.Sprintf("%s://%s:%s", protocol, host, port)) if err != nil { return fmt.Errorf("invalid url: %w", err) } for i := range packageCustomizationFiles { _, pErr := getPackageCustomFile(packageCustomizationFiles[i]) if pErr != nil { return pErr } } _, _, _, err = helpers.ParsePackageStrings(extraPackages) if err != nil { return err } // Validate registry mirrors _, err = parseRegistryMirrors(registryMirrors) return err } func getPackageCustomFile(input string) (v1alpha1.PackageCustomization, error) { // the format should be `:` s := strings.Split(input, ":") if len(s) != 2 { return v1alpha1.PackageCustomization{}, fmt.Errorf("ensure %s is formatted as :", input) } paths, err := helpers.GetAbsFilePaths([]string{s[1]}, false) if err != nil { return v1alpha1.PackageCustomization{}, err } err = helpers.ValidateKubernetesYamlFile(paths[0]) if err != nil { return v1alpha1.PackageCustomization{}, err } corePkgs := map[string]struct{}{v1alpha1.ArgoCDPackageName: {}, v1alpha1.GiteaPackageName: {}, v1alpha1.IngressNginxPackageName: {}} name := s[0] _, ok := corePkgs[name] if !ok { return v1alpha1.PackageCustomization{}, fmt.Errorf("customization for %s not supported", name) } return v1alpha1.PackageCustomization{ Name: name, FilePath: paths[0], }, nil } func parseRegistryMirrors(mirrors []string) ([]v1alpha1.RegistryMirror, error) { var result []v1alpha1.RegistryMirror for _, mirror := range mirrors { // Format: target=address (e.g. "docker.io=http://kind-registry:5000") parts := strings.SplitN(mirror, "=", 2) if len(parts) != 2 { return nil, fmt.Errorf("invalid registry mirror format: %s, expected format: target=address (e.g. docker.io=http://kind-registry:5000)", mirror) } target := strings.TrimSpace(parts[0]) address := strings.TrimSpace(parts[1]) if target == "" { return nil, fmt.Errorf("target registry cannot be empty in mirror: %s", mirror) } if address == "" { return nil, fmt.Errorf("registry address cannot be empty in mirror: %s", mirror) } // target must be [hostname|ip][:port] (https://github.com/containerd/containerd/blob/main/docs/hosts.md#registry-host-namespace) parsedTarget, err := url.Parse("https://" + target) if err != nil || parsedTarget.Host == "" || parsedTarget.Path != "" { return nil, fmt.Errorf("invalid target registry %q: expected format [hostname|ip][:port] (e.g. docker.io, 192.168.1.1:5000)", target) } // address must be a valid URL parsedURL, err := url.Parse(address) if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" { return nil, fmt.Errorf("invalid registry address URL: %s, expected format: http(s)://host:port", address) } result = append(result, v1alpha1.RegistryMirror{ TargetRegistry: target, RegistryAddress: address, }) } return result, nil } func printSuccessMsg() { subDomain := "argocd." subPath := "" if pathRouting == true { subDomain = "" subPath = "argocd" } var argoURL string proxy := behindProxy() if proxy { argoURL = fmt.Sprintf("https://%s/argocd", host) } else { argoURL = fmt.Sprintf("%s://%s%s:%s/%s", protocol, subDomain, host, port, subPath) } fmt.Print("\n\n########################### Finished Creating IDP Successfully! ############################\n\n\n") fmt.Printf("Can Access ArgoCD at %s\nUsername: admin\n", argoURL) fmt.Print(`Password can be retrieved by running: idpbuilder get secrets -p argocd`, "\n") } func behindProxy() bool { // check if we are in codespaces: https://docs.github.com/en/codespaces/developing-in-a-codespace/default-environment-variables-for-your-codespace _, ok := os.LookupEnv("CODESPACES") return ok } ================================================ FILE: pkg/cmd/create/root_test.go ================================================ package create import ( "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" ) func TestParseRegistryMirrors(t *testing.T) { type test struct { name string input []string expect []v1alpha1.RegistryMirror wantErr bool } tests := []test{ { name: "empty input", input: []string{}, expect: []v1alpha1.RegistryMirror{}, wantErr: false, }, { name: "single mirror", input: []string{"docker.io=http://kind-registry:5000"}, expect: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, wantErr: false, }, { name: "multiple mirrors", input: []string{"docker.io=http://kind-registry:5000", "ghcr.io=http://kind-registry:5000"}, expect: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, { TargetRegistry: "ghcr.io", RegistryAddress: "http://kind-registry:5000", }, }, wantErr: false, }, { name: "mirror with space", input: []string{" docker.io = http://kind-registry:5000 "}, expect: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, wantErr: false, }, { name: "missing equals", input: []string{"docker.io:http://kind-registry:5000"}, expect: nil, wantErr: true, }, { name: "empty target", input: []string{"=http://kind-registry:5000"}, expect: nil, wantErr: true, }, { name: "empty address", input: []string{"docker.io="}, expect: nil, wantErr: true, }, { name: "target with path", input: []string{"docker.io/library=http://my-registry:5000"}, wantErr: true, }, { name: "target with scheme", input: []string{"https://docker.io=http://my-registry:5000"}, wantErr: true, }, { name: "malformed address URL", input: []string{"docker.io=not-a-url"}, wantErr: true, }, { name: "mirror with https", input: []string{"docker.io=https://my-registry:5000"}, expect: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "https://my-registry:5000", }, }, wantErr: false, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result, err := parseRegistryMirrors(tc.input) if (err != nil) != tc.wantErr { t.Errorf("parseRegistryMirrors() error = %v, wantErr %v", err, tc.wantErr) return } if !tc.wantErr { if len(result) != len(tc.expect) { t.Errorf("parseRegistryMirrors() got %d mirrors, want %d", len(result), len(tc.expect)) return } for i := range result { if result[i].TargetRegistry != tc.expect[i].TargetRegistry { t.Errorf("parseRegistryMirrors()[%d].TargetRegistry = %v, want %v", i, result[i].TargetRegistry, tc.expect[i].TargetRegistry) } if result[i].RegistryAddress != tc.expect[i].RegistryAddress { t.Errorf("parseRegistryMirrors()[%d].RegistryAddress = %v, want %v", i, result[i].RegistryAddress, tc.expect[i].RegistryAddress) } } } }) } } ================================================ FILE: pkg/cmd/delete/root.go ================================================ package delete import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" "github.com/cnoe-io/idpbuilder/pkg/kind" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" "sigs.k8s.io/kind/pkg/cluster" ) var ( // Flags name string ) var DeleteCmd = &cobra.Command{ Use: "delete", Short: "Delete an IDP cluster", Long: ``, RunE: deleteE, PreRunE: preDeleteE, SilenceUsage: true, } func init() { DeleteCmd.PersistentFlags().StringVar(&name, "name", "localdev", "Name of the kind cluster to be deleted.") } func preDeleteE(cmd *cobra.Command, args []string) error { return helpers.SetLogger() } func deleteE(cmd *cobra.Command, args []string) error { logger := helpers.CmdLogger logger.Info("deleting cluster", "clusterName", name) detectOpt, err := util.DetectKindNodeProvider() if err != nil { return err } provider := cluster.NewProvider(cluster.ProviderWithLogger(kind.KindLoggerFromLogr(&logger)), detectOpt) if err := provider.Delete(name, ""); err != nil { return fmt.Errorf("failed to delete cluster %s: %w", name, err) } return nil } ================================================ FILE: pkg/cmd/get/clusters.go ================================================ package get import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/kind" "github.com/cnoe-io/idpbuilder/pkg/printer" idpTypes "github.com/cnoe-io/idpbuilder/pkg/printer/types" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" "os" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" "slices" "strings" ) // ClusterManager holds the clients for the different idpbuilder clusters type ClusterManager struct { clients map[string]client.Client // map of cluster name to client } var ClustersCmd = &cobra.Command{ Use: "clusters", Short: "Get idp clusters", Long: ``, RunE: list, PreRunE: preClustersE, SilenceUsage: true, } func preClustersE(cmd *cobra.Command, args []string) error { return helpers.SetLogger() } func list(cmd *cobra.Command, args []string) error { clusters, err := populateClusterList() if err != nil { return err } else { clusterPrinter := printer.ClusterPrinter{ Clusters: clusters, OutWriter: os.Stdout, } return clusterPrinter.PrintOutput(outputFormat) } } func populateClusterList() ([]idpTypes.Cluster, error) { logger := helpers.CmdLogger detectOpt, err := util.DetectKindNodeProvider() if err != nil { return nil, err } kubeConfig, err := util.GetKubeConfig() if err != nil { return nil, err } _, err = util.GetKubeClient(kubeConfig) if err != nil { return nil, err } config, err := util.LoadKubeConfig() if err != nil { //logger.Error(err, "failed to load the kube config.") return nil, err } // Create an empty array of clusters to collect the information clusterList := []idpTypes.Cluster{} // List the idp builder clusters according to the provider: podman or docker provider := cluster.NewProvider(cluster.ProviderWithLogger(kind.KindLoggerFromLogr(&logger)), detectOpt) clusters, err := provider.List() if err != nil { return nil, err } // Populate a list of Kube client for each cluster/context matching an idpbuilder cluster manager, err := CreateKubeClientForEachIDPCluster(config, clusters) if err != nil { return nil, err } for _, cluster := range clusters { aCluster := idpTypes.Cluster{Name: cluster} // Search about the idp cluster within the kubeconfig file and show information c, found := findClusterByName(config, "kind-"+cluster) if !found { logger.Info(fmt.Sprintf("Cluster not found: %s within kube config file\n", cluster)) } else { cli, err := GetClientForCluster(manager, cluster) if err != nil { return nil, err } logger.V(1).Info(fmt.Sprintf("Got the context for the cluster: %s.", cluster)) // Print the external port mounted on the container and available also as ingress host port targetPort, err := findExternalHTTPSPort(cli, cluster) if err != nil { return nil, err } else { aCluster.ExternalPort = targetPort } aCluster.URLKubeApi = c.Server aCluster.TlsCheck = c.InsecureSkipTLSVerify // Print the internal port running the Kube API service kubeApiPort, err := findInternalKubeApiPort(cli) if err != nil { return nil, err } else { aCluster.KubePort = kubeApiPort } // Let's check what the current node reports var nodeList corev1.NodeList err = cli.List(context.TODO(), &nodeList) if err != nil { return nil, err } for _, node := range nodeList.Items { nodeName := node.Name aNode := idpTypes.Node{} aNode.Name = nodeName for _, addr := range node.Status.Addresses { switch addr.Type { case corev1.NodeInternalIP: aNode.InternalIP = addr.Address case corev1.NodeExternalIP: aNode.ExternalIP = addr.Address } } // Get Node capacity resources := node.Status.Capacity memory := resources[corev1.ResourceMemory] cpu := resources[corev1.ResourceCPU] pods := resources[corev1.ResourcePods] aNode.Capacity = idpTypes.Capacity{ Memory: float64(memory.Value()) / (1024 * 1024 * 1024), Cpu: cpu.Value(), Pods: pods.Value(), } // Get Node Allocated resources allocated, err := printAllocatedResources(context.Background(), cli, node.Name) if err != nil { return nil, err } aNode.Allocated = allocated aCluster.Nodes = append(aCluster.Nodes, aNode) } } clusterList = append(clusterList, aCluster) } return clusterList, nil } func printAllocatedResources(ctx context.Context, k8sClient client.Client, nodeName string) (idpTypes.Allocated, error) { // List all pods on the specified node var podList corev1.PodList if err := k8sClient.List(ctx, &podList, client.MatchingFields{"spec.nodeName": nodeName}); err != nil { return idpTypes.Allocated{}, fmt.Errorf("failed to list pods on node %s.", nodeName) } // Initialize counters for CPU and memory requests totalCPU := resource.NewQuantity(0, resource.DecimalSI) totalMemory := resource.NewQuantity(0, resource.BinarySI) // Sum up CPU and memory requests from each container in each pod for _, pod := range podList.Items { for _, container := range pod.Spec.Containers { if reqCPU, found := container.Resources.Requests[corev1.ResourceCPU]; found { totalCPU.Add(reqCPU) } if reqMemory, found := container.Resources.Requests[corev1.ResourceMemory]; found { totalMemory.Add(reqMemory) } } } allocated := idpTypes.Allocated{ Memory: totalMemory.String(), Cpu: totalCPU.String(), } return allocated, nil } func findExternalHTTPSPort(cli client.Client, clusterName string) (int32, error) { service := corev1.Service{} namespacedName := types.NamespacedName{ Name: "ingress-nginx-controller", Namespace: "ingress-nginx", } err := cli.Get(context.TODO(), namespacedName, &service) if err != nil { return 0, fmt.Errorf("failed to get the ingress service on the cluster. %w", err) } localBuild := v1alpha1.Localbuild{ ObjectMeta: metav1.ObjectMeta{ Name: clusterName, }, } err = cli.Get(context.TODO(), client.ObjectKeyFromObject(&localBuild), &localBuild) if err != nil { return 0, fmt.Errorf("failed to get the localbuild on the cluster. %w", err) } var targetPort corev1.ServicePort protocol := localBuild.Spec.BuildCustomization.Protocol + "-" for _, port := range service.Spec.Ports { if port.Name != "" && strings.HasPrefix(port.Name, protocol) { targetPort = port break } } return targetPort.Port, nil } func findInternalKubeApiPort(cli client.Client) (int32, error) { service := corev1.Service{} namespacedName := types.NamespacedName{ Name: "kubernetes", Namespace: "default", } err := cli.Get(context.TODO(), namespacedName, &service) if err != nil { return 0, fmt.Errorf("failed to get the kubernetes default service on the cluster. %w", err) } var targetPort corev1.ServicePort for _, port := range service.Spec.Ports { if port.Name != "" && strings.HasPrefix(port.Name, "https") { targetPort = port break } } return targetPort.TargetPort.IntVal, nil } // findClusterByName searches for a cluster by name in the kubeconfig func findClusterByName(config *api.Config, name string) (*api.Cluster, bool) { cluster, exists := config.Clusters[name] return cluster, exists } // GetClientForCluster returns the client for the specified cluster/context name func GetClientForCluster(m *ClusterManager, clusterName string) (client.Client, error) { cl, exists := m.clients["kind-"+clusterName] if !exists { return nil, fmt.Errorf("no client found for cluster %q", clusterName) } return cl, nil } func CreateKubeClientForEachIDPCluster(config *api.Config, clusterList []string) (*ClusterManager, error) { // Initialize the ClusterManager with a map of kube Client manager := &ClusterManager{ clients: make(map[string]client.Client), } for contextName := range config.Contexts { // Check if the kubconfig contains the cluster name // We remove the prefix "kind-" to find the cluster name from the slice if slices.Contains(clusterList, contextName[5:]) { cfg, err := clientcmd.NewNonInteractiveClientConfig(*config, contextName, &clientcmd.ConfigOverrides{}, nil).ClientConfig() if err != nil { return nil, fmt.Errorf("Failed to build client for context %s.", contextName) } cl, err := client.New(cfg, client.Options{Scheme: k8s.GetScheme()}) if err != nil { return nil, fmt.Errorf("failed to create client for context %s", contextName) } manager.clients[contextName] = cl } } return manager, nil } ================================================ FILE: pkg/cmd/get/packages.go ================================================ package get import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/printer" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" "io" "os" "sigs.k8s.io/controller-runtime/pkg/client" "strconv" ) var PackagesCmd = &cobra.Command{ Use: "packages", Short: "retrieve packages from the cluster", Long: ``, RunE: getPackagesE, SilenceUsage: true, } func getPackagesE(cmd *cobra.Command, args []string) error { ctx, ctxCancel := context.WithCancel(cmd.Context()) defer ctxCancel() kubeConfig, err := util.GetKubeConfig() if err != nil { return fmt.Errorf("getting kube config: %w", err) } kubeClient, err := util.GetKubeClient(kubeConfig) if err != nil { return fmt.Errorf("getting kube client: %w", err) } return printPackages(ctx, os.Stdout, kubeClient, outputFormat) } // Print all the custom packages or based on package arguments passed using flag: -p func printPackages(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { packageList := []types.Package{} customPackages := v1alpha1.CustomPackageList{} var err error idpbuilderNamespace, err := getIDPNamespace(ctx, kubeClient) if err != nil { return fmt.Errorf("getting namespace: %w", err) } config, err := util.GetConfig(ctx) if err != nil { return fmt.Errorf("getting idp config: %w", err) } argocdBaseUrl := util.ArgocdBaseUrl(config) if len(packages) == 0 { // Get all custom packages customPackages, err = getPackages(ctx, kubeClient, idpbuilderNamespace) if err != nil { return fmt.Errorf("listing custom packages: %w", err) } } else { // Get the custom package using its name for _, name := range packages { cp, err := getPackageByName(ctx, kubeClient, idpbuilderNamespace, name) if err != nil { return fmt.Errorf("getting custom package %s: %w", name, err) } customPackages.Items = append(customPackages.Items, cp) } } for _, cp := range customPackages.Items { newPackage := types.Package{} newPackage.Name = cp.Name newPackage.Namespace = cp.Namespace newPackage.ArgocdRepository = argocdBaseUrl + "/applications/" + cp.Spec.ArgoCD.Namespace + "/" + cp.Spec.ArgoCD.Name // There is a GitRepositoryRefs when the project has been cloned to the internal git repository if cp.Status.GitRepositoryRefs != nil { newPackage.GitRepository = cp.Spec.InternalGitServeURL + "/" + v1alpha1.GiteaAdminUserName + "/" + idpbuilderNamespace + "-" + cp.Status.GitRepositoryRefs[0].Name } else { // Default branch reference ref := "main" if cp.Spec.RemoteRepository.Ref != "" { ref = cp.Spec.RemoteRepository.Ref } newPackage.GitRepository = cp.Spec.RemoteRepository.Url + "/tree/" + ref + "/" + cp.Spec.RemoteRepository.Path } newPackage.Status = strconv.FormatBool(cp.Status.Synced) packageList = append(packageList, newPackage) } packagePrinter := printer.PackagePrinter{ Packages: packageList, OutWriter: outWriter, } return packagePrinter.PrintOutput(format) } func getPackageByName(ctx context.Context, kubeClient client.Client, ns, name string) (v1alpha1.CustomPackage, error) { p := v1alpha1.CustomPackage{} return p, kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: ns}, &p) } func getIDPNamespace(ctx context.Context, kubeClient client.Client) (string, error) { build, err := getLocalBuild(ctx, kubeClient) if err != nil { return "", err } // TODO: We assume that only one LocalBuild has been created for one cluster ! idpNamespace := v1alpha1.FieldManager + "-" + build.Items[0].Name return idpNamespace, nil } func getLocalBuild(ctx context.Context, kubeClient client.Client) (v1alpha1.LocalbuildList, error) { localBuildList := v1alpha1.LocalbuildList{} return localBuildList, kubeClient.List(ctx, &localBuildList) } func getPackages(ctx context.Context, kubeClient client.Client, ns string) (v1alpha1.CustomPackageList, error) { packageList := v1alpha1.CustomPackageList{} return packageList, kubeClient.List(ctx, &packageList, client.InNamespace(ns)) } ================================================ FILE: pkg/cmd/get/root.go ================================================ package get import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" ) var GetCmd = &cobra.Command{ Use: "get", Short: "get information from the cluster", Long: ``, RunE: exportE, } var ( packages []string outputFormat string ) func init() { GetCmd.AddCommand(ClustersCmd) GetCmd.AddCommand(SecretsCmd) GetCmd.AddCommand(PackagesCmd) GetCmd.PersistentFlags().StringSliceVarP(&packages, "packages", "p", []string{}, "names of packages.") GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "table", "Output format: table (default if not specified), json or yaml.") GetCmd.PersistentFlags().StringVarP(&util.KubeConfigPath, "kubeconfig", "", "", "kube config file Path.") } func exportE(cmd *cobra.Command, args []string) error { return fmt.Errorf("specify subcommand") } ================================================ FILE: pkg/cmd/get/secrets.go ================================================ package get import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/printer" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" "io" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" "os" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( argoCDAdminUsername = "admin" argoCDInitialAdminSecretName = "argocd-initial-admin-secret" giteaAdminSecretName = "gitea-credential" ) var SecretsCmd = &cobra.Command{ Use: "secrets", Short: "retrieve secrets from the cluster", Long: ``, RunE: getSecretsE, SilenceUsage: true, } // well known secrets that are part of the core packages var ( corePkgSecrets = map[string][]string{ "argocd": []string{argoCDInitialAdminSecretName}, "gitea": []string{giteaAdminSecretName}, } ) func getSecretsE(cmd *cobra.Command, args []string) error { ctx, ctxCancel := context.WithCancel(cmd.Context()) defer ctxCancel() kubeConfig, err := util.GetKubeConfig() if err != nil { return fmt.Errorf("getting kube config: %w", err) } kubeClient, err := util.GetKubeClient(kubeConfig) if err != nil { return fmt.Errorf("getting kube client: %w", err) } if len(packages) == 0 { return printAllPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) } return printPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) } func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() secrets := []types.Secret{} secretPrinter := printer.SecretPrinter{ Secrets: secrets, OutWriter: outWriter, } for k, v := range corePkgSecrets { for i := range v { secret, sErr := getCorePackageSecret(ctx, kubeClient, k, v[i]) if sErr != nil { if errors.IsNotFound(sErr) { continue } return fmt.Errorf("getting secret %s in %s: %w", v[i], k, sErr) } secrets = append(secrets, populateSecret(secret, true)) } } cnoeLabelSecrets, err := getSecretsByCNOELabel(ctx, kubeClient, selector) if err != nil { return fmt.Errorf("listing secrets: %w", err) } for i := range cnoeLabelSecrets.Items { secrets = append(secrets, populateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { fmt.Println("no secrets found") return nil } secretPrinter.Secrets = secrets return secretPrinter.PrintOutput(format) } func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() secrets := []types.Secret{} secretPrinter := printer.SecretPrinter{ OutWriter: outWriter, } for i := range packages { p := packages[i] secretNames, ok := corePkgSecrets[p] if ok { for j := range secretNames { secret, sErr := getCorePackageSecret(ctx, kubeClient, p, secretNames[j]) if sErr != nil { if errors.IsNotFound(sErr) { continue } return fmt.Errorf("getting secret %s in %s: %w", secretNames[j], p, sErr) } secrets = append(secrets, populateSecret(secret, true)) } continue } req, pErr := labels.NewRequirement(v1alpha1.PackageNameLabelKey, selection.Equals, []string{p}) if pErr != nil { return fmt.Errorf("building requirement for %s: %w", p, pErr) } pkgSelector := selector.Add(*req) cnoeLabelSecrets, err := getSecretsByCNOELabel(ctx, kubeClient, pkgSelector) if err != nil { return fmt.Errorf("listing secrets: %w", err) } for i := range cnoeLabelSecrets.Items { secrets = append(secrets, populateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { fmt.Println("no secrets found") return nil } } secretPrinter.Secrets = secrets return secretPrinter.PrintOutput(format) } func populateSecret(s v1.Secret, isCoreSecret bool) types.Secret { secret := types.Secret{ Name: s.Name, Namespace: s.Namespace, } if isCoreSecret { secret.IsCore = true secret.Username = string(s.Data["username"]) secret.Password = string(s.Data["password"]) secret.Token = string(s.Data["token"]) secret.Data = nil } else { newData := make(map[string]string) for key, value := range s.Data { newData[key] = string(value) } if len(newData) > 0 { secret.Data = newData } } return secret } func getSecretsByCNOELabel(ctx context.Context, kubeClient client.Client, l labels.Selector) (v1.SecretList, error) { req, err := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) if err != nil { return v1.SecretList{}, fmt.Errorf("building labels with key %s and value %s : %w", v1alpha1.CLISecretLabelKey, v1alpha1.CLISecretLabelValue, err) } secrets := v1.SecretList{} opts := client.ListOptions{ LabelSelector: l.Add(*req), Namespace: "", // find in all namespaces } return secrets, kubeClient.List(ctx, &secrets, &opts) } func getCorePackageSecret(ctx context.Context, kubeClient client.Client, ns, name string) (v1.Secret, error) { s, err := util.GetSecretByName(ctx, kubeClient, ns, name) if err != nil { return v1.Secret{}, err } if name == argoCDInitialAdminSecretName && s.Data != nil { s.Data["username"] = []byte(argoCDAdminUsername) } return s, nil } ================================================ FILE: pkg/cmd/get/secrets_test.go ================================================ package get import ( "bytes" "context" "encoding/json" "io" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" "sigs.k8s.io/controller-runtime/pkg/client" ) type fakeKubeClient struct { mock.Mock client.Client } func (f *fakeKubeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { args := f.Called(ctx, key, obj, opts) return args.Error(0) } func (f *fakeKubeClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { args := f.Called(ctx, list, opts) return args.Error(0) } type cases struct { err error packages []string getKeys []client.ObjectKey listLabelSelector []labels.Selector } func selector(pkgName string) labels.Selector { r1, _ := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) r2, _ := labels.NewRequirement(v1alpha1.PackageNameLabelKey, selection.Equals, []string{pkgName}) return labels.NewSelector().Add(*r1).Add(*r2) } func TestPrintPackageSecrets(t *testing.T) { ctx := context.Background() cs := []cases{ { err: nil, packages: []string{"abc"}, listLabelSelector: []labels.Selector{selector("abc")}, }, { err: nil, packages: []string{"argocd", "gitea", "abc"}, listLabelSelector: []labels.Selector{selector("abc")}, getKeys: []client.ObjectKey{ {Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, {Name: giteaAdminSecretName, Namespace: "gitea"}, }, }, { err: nil, packages: []string{"argocd", "gitea"}, getKeys: []client.ObjectKey{ {Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, {Name: giteaAdminSecretName, Namespace: "gitea"}, }, }, { err: nil, packages: []string{"argocd"}, getKeys: []client.ObjectKey{ {Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, }, }, } for i := range cs { c := cs[i] fClient := new(fakeKubeClient) packages = c.packages for j := range c.listLabelSelector { opts := client.ListOptions{ LabelSelector: c.listLabelSelector[j], Namespace: "", } fClient.On("List", ctx, mock.Anything, []client.ListOption{&opts}).Return(c.err) } for j := range c.getKeys { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } err := printPackageSecrets(ctx, io.Discard, fClient, "table") fClient.AssertExpectations(t) assert.Nil(t, err) } } func TestPrintAllPackageSecrets(t *testing.T) { ctx := context.Background() r, _ := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) cs := []cases{ { err: nil, listLabelSelector: []labels.Selector{labels.NewSelector().Add(*r)}, getKeys: []client.ObjectKey{ {Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, {Name: giteaAdminSecretName, Namespace: "gitea"}, }, }, } for i := range cs { c := cs[i] fClient := new(fakeKubeClient) for j := range c.listLabelSelector { opts := client.ListOptions{ LabelSelector: c.listLabelSelector[j], Namespace: "", } fClient.On("List", ctx, mock.Anything, []client.ListOption{&opts}).Return(c.err) } for j := range c.getKeys { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } err := printAllPackageSecrets(ctx, io.Discard, fClient, "table") fClient.AssertExpectations(t) assert.Nil(t, err) } } func TestOutput(t *testing.T) { ctx := context.Background() r, _ := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) corePkgData := map[string]types.Secret{ argoCDInitialAdminSecretName: { IsCore: true, Name: argoCDInitialAdminSecretName, Namespace: "argocd", Username: "admin", Password: "abc", }, giteaAdminSecretName: { IsCore: true, Name: giteaAdminSecretName, Namespace: "gitea", Username: "admin", Password: "abc", }, } packageData := map[string]types.Secret{ "name1": { Name: "name1", Namespace: "ns1", Data: map[string]string{ "data1": "data1", "data2": "data2", }, }, "name2": { Name: "name2", Namespace: "ns2", Data: map[string]string{ "data1": "data1", "data2": "data2", }, }, } fClient := new(fakeKubeClient) opts := client.ListOptions{ LabelSelector: labels.NewSelector().Add(*r), Namespace: "", } fClient.On("Get", ctx, client.ObjectKey{Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1.Secret) sec := secretDataToSecret(corePkgData[argoCDInitialAdminSecretName]) *arg = sec }).Return(nil) fClient.On("Get", ctx, client.ObjectKey{Name: giteaAdminSecretName, Namespace: "gitea"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1.Secret) sec := secretDataToSecret(corePkgData[giteaAdminSecretName]) *arg = sec }).Return(nil) fClient.On("List", ctx, mock.Anything, []client.ListOption{&opts}).Run(func(args mock.Arguments) { arg := args.Get(1).(*v1.SecretList) secs := make([]v1.Secret, 0, 2) for k := range packageData { s := secretDataToSecret(packageData[k]) secs = append(secs, s) } arg.Items = secs }).Return(nil) var b []byte buffer := bytes.NewBuffer(b) err := printAllPackageSecrets(ctx, buffer, fClient, "json") fClient.AssertExpectations(t) assert.Nil(t, err) // verify received json data var received []types.Secret err = json.Unmarshal(buffer.Bytes(), &received) assert.Nil(t, err) assert.Equal(t, 4, len(received)) for i := range received { rec := received[i] c, ok := corePkgData[rec.Name] if ok { // Set the IsCore bool field to true as the v1.Secret don't include it ! rec.IsCore = true assert.Equal(t, c, rec) delete(corePkgData, rec.Name) continue } else { d, okE := packageData[rec.Name] if okE { assert.Equal(t, d, rec) delete(packageData, rec.Name) continue } t.Fatalf("found an invalid element: %s", rec.Name) } } assert.Equal(t, 0, len(corePkgData)) assert.Equal(t, 0, len(packageData)) } func secretDataToSecret(data types.Secret) v1.Secret { d := make(map[string][]byte) if data.IsCore { d["username"] = []byte(data.Username) d["password"] = []byte(data.Password) d["token"] = []byte(data.Token) } else { for k := range data.Data { d[k] = []byte(data.Data[k]) } } return v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: data.Name, Namespace: data.Namespace}, Data: d, } } ================================================ FILE: pkg/cmd/helpers/logger.go ================================================ package helpers import ( "fmt" "log/slog" "os" "strings" "github.com/cnoe-io/idpbuilder/pkg/logger" "github.com/go-logr/logr" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" ) var ( LogLevel string LogLevelMsg = "Set the log verbosity. Supported values are: debug, info, warn, and error." CmdLogger logr.Logger ColoredOutput bool ColoredOutputMsg = "Enable colored log messages." ) func SetLogger() error { l, err := getSlogLevel(LogLevel) if err != nil { return err } slogger := slog.New(logger.NewHandler(os.Stderr, logger.Options{Level: l, Colored: ColoredOutput})) kslogger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: getKlogLevel(l)})) logger := logr.FromSlogHandler(slogger.Handler()) klogger := logr.FromSlogHandler(kslogger.Handler()) klog.SetLogger(klogger) ctrl.SetLogger(logger) CmdLogger = logger return nil } func getSlogLevel(s string) (slog.Level, error) { switch strings.ToLower(s) { case "debug": return slog.LevelDebug, nil case "info": return slog.LevelInfo, nil case "warn": return slog.LevelWarn, nil case "error": return slog.LevelError, nil default: return slog.LevelDebug, fmt.Errorf("%s is not a valid log level", s) } } // For end users, klog messages are mostly useless. We set it to error level unless debug logging is enabled. func getKlogLevel(l slog.Level) slog.Level { if l < slog.LevelInfo { return l } return slog.LevelError } ================================================ FILE: pkg/cmd/helpers/test-data/notk8s.yaml ================================================ name: me pluto: not a planet ================================================ FILE: pkg/cmd/helpers/test-data/notyaml.yaml ================================================ not: a yaml ================================================ FILE: pkg/cmd/helpers/test-data/valid.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 --- apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce storageClassName: standard hostPath: path: /mnt/data --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 ================================================ FILE: pkg/cmd/helpers/validation.go ================================================ package helpers import ( "fmt" "os" "path/filepath" "github.com/cnoe-io/idpbuilder/pkg/util" "sigs.k8s.io/kustomize/kyaml/kio" ) func ValidateKubernetesYamlFile(absPath string) error { if !filepath.IsAbs(absPath) { return fmt.Errorf("given path is not an absolute path %s", absPath) } b, err := os.ReadFile(absPath) if err != nil { return fmt.Errorf("failed reading file: %s, err: %w", absPath, err) } n, err := kio.FromBytes(b) if err != nil { return fmt.Errorf("failed parsing file as kubernetes manifests file: %s, err: %w", absPath, err) } for i := range n { obj := n[i] if obj.IsNilOrEmpty() { return fmt.Errorf("given file %s contains an invalid kubernetes manifest", absPath) } if obj.GetKind() == "" || obj.GetApiVersion() == "" { return fmt.Errorf("given file %s contains an invalid kubernetes manifest", absPath) } } return nil } func ParsePackageStrings(pkgStrings []string) ([]string, []string, []string, error) { remote, files, dirs := make([]string, 0, 2), make([]string, 0, 2), make([]string, 0, 2) for i := range pkgStrings { loc := pkgStrings[i] _, err := util.NewKustomizeRemote(loc) if err == nil { remote = append(remote, loc) continue } absPath, err := getAbsPath(loc, true) if err == nil { dirs = append(dirs, absPath) continue } absPath, err = getAbsPath(loc, false) if err == nil { files = append(files, absPath) continue } return nil, nil, nil, err } return remote, files, dirs, nil } func getAbsPath(path string, isDir bool) (string, error) { absPath, err := filepath.Abs(path) if err != nil { return "", fmt.Errorf("failed to validate path %s : %w", path, err) } f, err := os.Stat(absPath) if err != nil { return "", fmt.Errorf("failed to validate path %s : %w", absPath, err) } if isDir && !f.IsDir() { return "", fmt.Errorf("given path is not a directory. %s", absPath) } if !isDir && !f.Mode().IsRegular() { return "", fmt.Errorf("given path is not a file. %s", absPath) } return absPath, nil } func GetAbsFilePaths(paths []string, isDir bool) ([]string, error) { out := make([]string, len(paths)) for i := range paths { absPath, err := getAbsPath(paths[i], isDir) if err != nil { return nil, err } out[i] = absPath } return out, nil } ================================================ FILE: pkg/cmd/helpers/validation_test.go ================================================ package helpers import ( "fmt" "os" "testing" "github.com/stretchr/testify/assert" ) func TestValidateKubernetesYaml(t *testing.T) { cwd, err := os.Getwd() if err != nil { t.Fatalf("could not get current working directory") } cases := map[string]struct { expectErr bool inputPath string }{ "invalidPath": {expectErr: true, inputPath: fmt.Sprintf("%s/invalid/path", cwd)}, "notAbs": {expectErr: true, inputPath: fmt.Sprintf("invalid/path")}, "valid": {expectErr: false, inputPath: fmt.Sprintf("%s/test-data/valid.yaml", cwd)}, "notYaml": {expectErr: true, inputPath: fmt.Sprintf("%s/test-data/notyaml.yaml", cwd)}, "notk8s": {expectErr: true, inputPath: fmt.Sprintf("%s/test-data/notk8s.yaml", cwd)}, } for k := range cases { cErr := ValidateKubernetesYamlFile(cases[k].inputPath) if cases[k].expectErr && cErr == nil { t.Fatalf("%s expected error but did not receive error", k) } if !cases[k].expectErr && cErr != nil { t.Fatalf("%s did not expect error but received error", k) } } } func TestParsePackageStrings(t *testing.T) { cases := map[string]struct { expectErr bool inputPaths []string remote int files int dirs int }{ "allDirs": {expectErr: false, inputPaths: []string{"test-data", "."}, remote: 0, files: 0, dirs: 2}, "allFiles": {expectErr: false, inputPaths: []string{"test-data/valid.yaml"}, remote: 0, files: 1, dirs: 0}, "allRemote": {expectErr: false, inputPaths: []string{ "https://github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?timeout=120&ref=v3.3.1", "git@github.com:owner/repo//examples", }, remote: 2, files: 0, dirs: 0}, "mix": {expectErr: false, inputPaths: []string{ "https://github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?timeout=120&ref=v3.3.1", "test-data", "test-data/valid.yaml", }, remote: 1, files: 1, dirs: 1}, "invalidLocalPath": {expectErr: true, inputPaths: []string{ "does-not-exist", }, remote: 0, files: 0, dirs: 0}, "invalidRemotePath": {expectErr: true, inputPaths: []string{ "https:// github.com/kubernetes-sigs/kustomize//examples", }, remote: 0, files: 0, dirs: 0}, } for k := range cases { c := cases[k] remote, files, dirs, err := ParsePackageStrings(c.inputPaths) if cases[k].expectErr { assert.NotNil(t, err) } else { assert.Nil(t, err) } assert.Equal(t, c.remote, len(remote)) assert.Equal(t, c.files, len(files)) assert.Equal(t, c.dirs, len(dirs)) } } ================================================ FILE: pkg/cmd/root.go ================================================ package cmd import ( "context" "fmt" "os" "github.com/cnoe-io/idpbuilder/pkg/cmd/create" "github.com/cnoe-io/idpbuilder/pkg/cmd/delete" "github.com/cnoe-io/idpbuilder/pkg/cmd/get" "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" "github.com/cnoe-io/idpbuilder/pkg/cmd/version" "github.com/spf13/cobra" ) var rootCmd = &cobra.Command{ Use: "idpbuilder", Short: "Manage reference IDPs", Long: "", } func init() { rootCmd.PersistentFlags().StringVarP(&helpers.LogLevel, "log-level", "l", "info", helpers.LogLevelMsg) rootCmd.PersistentFlags().BoolVar(&helpers.ColoredOutput, "color", false, helpers.ColoredOutputMsg) rootCmd.AddCommand(create.CreateCmd) rootCmd.AddCommand(get.GetCmd) rootCmd.AddCommand(delete.DeleteCmd) rootCmd.AddCommand(version.VersionCmd) } func Execute(ctx context.Context) { if err := rootCmd.ExecuteContext(ctx); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } ================================================ FILE: pkg/cmd/version/root.go ================================================ package version import ( "encoding/json" "fmt" "runtime" "github.com/spf13/cobra" "sigs.k8s.io/yaml" ) var ( // Flags outputFormat string ) var VersionCmd = &cobra.Command{ Use: "version", Short: "Print idpbuilder version and environment info", Long: "Print idpbulider version and environment info. This is useful in bug reports and CI.", RunE: version, } func init() { VersionCmd.Flags().StringVarP(&outputFormat, "output", "o", "", `Print the idpbuilder version information in a given output format. Accepts "wide", "json", and "yaml".`) } var ( idpbuilderVersion = "unknown" goVersion = runtime.Version() goOs = runtime.GOOS goArch = runtime.GOARCH gitCommit = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) buildDate = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') ) type idpbuilderInfo struct { IdpbuilderVersion string `json:"idpbuilderVersion"` GoVersion string `json:"goVersion"` GoOs string `json:"goOs"` GoArch string `json:"goArch"` GitCommit string `json:"gitCommit"` BuildDate string `json:"buildDate"` } func version(cmd *cobra.Command, args []string) error { switch outputFormat { case "wide": cmd.Println(fmt.Sprintf("Version: %#v", idpbuilderInfo{ idpbuilderVersion, goVersion, goOs, goArch, gitCommit, buildDate, })) case "json": jsonInfo, err := jsonInfo() if err != nil { return err } cmd.Println(jsonInfo) case "yaml": yamlInfo, err := yamlInfo() if err != nil { return err } cmd.Println(yamlInfo) case "": cmd.Println(fmt.Sprintf("idpbuilder %s %s %s/%s", idpbuilderVersion, goVersion, goOs, goArch)) default: return fmt.Errorf("invalid output format: %s", outputFormat) } return nil } func jsonInfo() (string, error) { info := idpbuilderInfo{ IdpbuilderVersion: idpbuilderVersion, GoVersion: goVersion, GoOs: goOs, GoArch: goArch, GitCommit: gitCommit, BuildDate: buildDate, } bytes, err := json.Marshal(info) if err != nil { return "", err } return string(bytes), nil } func yamlInfo() (string, error) { info := idpbuilderInfo{ IdpbuilderVersion: idpbuilderVersion, GoVersion: goVersion, GoOs: goOs, GoArch: goArch, GitCommit: gitCommit, BuildDate: buildDate, } bytes, err := yaml.Marshal(info) if err != nil { return "", err } return string(bytes), nil } ================================================ FILE: pkg/controllers/crd.go ================================================ package controllers import ( "context" "embed" "fmt" "github.com/cnoe-io/idpbuilder/pkg/util/fs" "time" "github.com/cnoe-io/idpbuilder/pkg/k8s" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) //go:embed resources/*.yaml var crdFS embed.FS func getK8sResources(scheme *runtime.Scheme, templateData any) ([]client.Object, error) { rawResources, err := fs.ConvertFSToBytes(crdFS, "resources", templateData) if err != nil { return nil, err } return k8s.ConvertRawResourcesToObjects(scheme, rawResources) } func EnsureCRD(ctx context.Context, scheme *runtime.Scheme, kubeClient client.Client, obj client.Object) error { logger := log.FromContext(ctx) // Check if the CRD already exists crd, ok := obj.(*apiextensionsv1.CustomResourceDefinition) if !ok { return fmt.Errorf("non crd object passed to EnsureCRD: %v", obj) } var curCRD apiextensionsv1.CustomResourceDefinition err := kubeClient.Get( ctx, types.NamespacedName{Name: obj.GetName(), Namespace: "default"}, &curCRD) switch { case apierrors.IsNotFound(err): if err := kubeClient.Create(ctx, obj); err != nil { logger.Error(err, "Unable to create CRD", "resource", obj) return err } case err != nil: logger.Error(err, "Unable to get CRD during initial check", "resource", obj) return err default: crd.SetResourceVersion(curCRD.GetResourceVersion()) if err = kubeClient.Update(ctx, crd); err != nil { logger.Error(err, "Updating CRD", "resource", obj) return err } } // There is some async work before the CRD actually exists, wait for this for { if err := kubeClient.Get( ctx, types.NamespacedName{Name: obj.GetName(), Namespace: "default"}, &curCRD, ); err != nil { logger.Error(err, "Failed to get CRD", "crd name", obj.GetName()) return err } crdEstablished := false for _, cond := range curCRD.Status.Conditions { if cond.Type == apiextensionsv1.Established { if cond.Status == apiextensionsv1.ConditionTrue { crdEstablished = true } } } if crdEstablished { break } else { logger.V(1).Info("crd not yet established, waiting.", "crd name", obj.GetName()) } time.Sleep(time.Duration(time.Duration.Milliseconds(500))) } return nil } func EnsureCRDs(ctx context.Context, scheme *runtime.Scheme, kubeClient client.Client, templateData any) error { installObjs, err := getK8sResources(scheme, templateData) if err != nil { return err } for _, obj := range installObjs { if err = EnsureCRD(ctx, scheme, kubeClient, obj); err != nil { return err } } return nil } ================================================ FILE: pkg/controllers/custompackage/controller.go ================================================ package custompackage import ( "context" "encoding/json" "fmt" "os" "path/filepath" "strings" "time" argocdapplication "github.com/cnoe-io/argocd-api/api/argo/application" argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/util" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" ) const ( requeueTime = time.Second * 30 ) type Reconciler struct { client.Client Recorder record.EventRecorder Scheme *runtime.Scheme Config v1alpha1.BuildCustomizationSpec TempDir string RepoMap *util.RepoMap } func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx) pkg := v1alpha1.CustomPackage{} err := r.Get(ctx, req.NamespacedName, &pkg) if err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } logger.V(1).Info("reconciling custom package", "name", req.Name, "namespace", req.Namespace) defer r.postProcessReconcile(ctx, req, &pkg) result, err := r.reconcileCustomPackage(ctx, &pkg) if err != nil { r.Recorder.Event(&pkg, "Warning", "reconcile error", err.Error()) } else { r.Recorder.Event(&pkg, "Normal", "reconcile success", "Successfully reconciled") } return result, err } func (r *Reconciler) postProcessReconcile(ctx context.Context, req ctrl.Request, pkg *v1alpha1.CustomPackage) { logger := log.FromContext(ctx) err := r.Status().Update(ctx, pkg) if err != nil { logger.Error(err, "failed updating repo status") } err = util.UpdateSyncAnnotation(ctx, r.Client, pkg) if err != nil { logger.Error(err, "failed updating repo annotation") } } // shouldTakeOverGitRepository checks if this CustomPackage should take over an existing GitRepository. // Returns true if this package has higher priority than the current owner. func (r *Reconciler) shouldTakeOverGitRepository(ctx context.Context, resource *v1alpha1.CustomPackage, existingRepo *v1alpha1.GitRepository) (bool, error) { logger := log.FromContext(ctx) // Get this package's priority thisPriority, err := getPackagePriority(resource) if err != nil { // If no priority annotation, assume it's a legacy package - allow takeover for backward compat logger.V(1).Info("no priority on this package, allowing takeover", "package", resource.Name) return true, nil } // Check the existing repo's owner references for _, ownerRef := range existingRepo.GetOwnerReferences() { if ownerRef.Kind == "CustomPackage" { // Fetch the owner CustomPackage to get its priority ownerPkg := &v1alpha1.CustomPackage{} err := r.Client.Get(ctx, client.ObjectKey{ Name: ownerRef.Name, Namespace: existingRepo.Namespace, }, ownerPkg) if err != nil { if errors.IsNotFound(err) { // Owner doesn't exist anymore, we can take over logger.Info("GitRepository owner not found, taking over", "repo", existingRepo.Name) return true, nil } return false, fmt.Errorf("getting owner package: %w", err) } // Get owner's priority ownerPriority, err := getPackagePriority(ownerPkg) if err != nil { // Owner has no priority, we can take over logger.V(1).Info("GitRepository owner has no priority, taking over", "repo", existingRepo.Name) return true, nil } // Only take over if we have HIGHER priority (higher number wins) if thisPriority > ownerPriority { logger.Info("Taking over GitRepository from lower priority owner", "repo", existingRepo.Name, "ourPriority", thisPriority, "ownerPriority", ownerPriority, "owner", ownerPkg.Name) return true, nil } else { logger.Info("Not taking over GitRepository owned by higher/equal priority package", "repo", existingRepo.Name, "ourPriority", thisPriority, "ownerPriority", ownerPriority, "owner", ownerPkg.Name) return false, nil } } } // No CustomPackage owner found, we can take over logger.V(1).Info("GitRepository has no CustomPackage owner, taking over", "repo", existingRepo.Name) return true, nil } // shouldReconcile checks if this CustomPackage should proceed with reconciliation. // It returns true only if this is the highest priority CustomPackage for the same app. func (r *Reconciler) shouldReconcile(ctx context.Context, resource *v1alpha1.CustomPackage) (bool, error) { logger := log.FromContext(ctx) // Get this package's priority thisPriority, err := getPackagePriority(resource) if err != nil { // If no priority annotation, assume it's a legacy package and allow it logger.V(1).Info("no priority annotation found, assuming legacy package", "name", resource.Name) return true, nil } // List all CustomPackages in the same namespace pkgList := &v1alpha1.CustomPackageList{} err = r.Client.List(ctx, pkgList, client.InNamespace(resource.Namespace)) if err != nil { return false, fmt.Errorf("listing custom packages: %w", err) } // Check if any other CustomPackage has the same app name with higher priority for i := range pkgList.Items { pkg := &pkgList.Items[i] // Skip self if pkg.Name == resource.Name { continue } // Skip if different app name if pkg.Spec.ArgoCD.Name != resource.Spec.ArgoCD.Name { continue } // Get the other package's priority otherPriority, err := getPackagePriority(pkg) if err != nil { // If the other package has no priority, this one wins continue } // If another package has higher priority, this one should not reconcile if otherPriority > thisPriority { thisSource := resource.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation] otherSource := pkg.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation] logger.Info("Yielding to higher priority package - skipping all reconciliation", "appName", resource.Spec.ArgoCD.Name, "yieldingPackage", thisSource, "yieldingPriority", thisPriority, "activePackage", otherSource, "activePriority", otherPriority) return false, nil } } return true, nil } // getPackagePriority extracts the priority from a CustomPackage's annotations func getPackagePriority(pkg *v1alpha1.CustomPackage) (int, error) { if pkg.ObjectMeta.Annotations == nil { return 0, fmt.Errorf("no annotations") } priorityStr, ok := pkg.ObjectMeta.Annotations[v1alpha1.PackagePriorityAnnotation] if !ok { return 0, fmt.Errorf("no priority annotation") } var priority int _, err := fmt.Sscanf(priorityStr, "%d", &priority) if err != nil { return 0, fmt.Errorf("invalid priority format: %w", err) } return priority, nil } // create an in-cluster repository CR, update the application spec, then apply func (r *Reconciler) reconcileCustomPackage(ctx context.Context, resource *v1alpha1.CustomPackage) (ctrl.Result, error) { logger := log.FromContext(ctx) // Check if this package should reconcile shouldReconcile, err := r.shouldReconcile(ctx, resource) if err != nil { return ctrl.Result{}, fmt.Errorf("checking if should reconcile: %w", err) } if !shouldReconcile { // This package has been superseded by a higher priority package // Mark as not synced and don't update resources, and don't requeue logger.Info("package superseded by higher priority, skipping reconciliation", "name", resource.Name, "appName", resource.Spec.ArgoCD.Name, "sourcePath", resource.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation]) resource.Status.Synced = false return ctrl.Result{}, nil } logger.V(1).Info("proceeding with reconciliation as highest priority package", "name", resource.Name, "appName", resource.Spec.ArgoCD.Name) b, err := r.getArgoCDAppFile(ctx, resource) if err != nil { return ctrl.Result{}, fmt.Errorf("reading file %s: %w", resource.Spec.ArgoCD.ApplicationFile, err) } objs, err := k8s.ConvertYamlToObjects(r.Scheme, b) if err != nil { return ctrl.Result{}, fmt.Errorf("converting yaml to object %w", err) } if len(objs) == 0 { return ctrl.Result{}, fmt.Errorf("file contained 0 kubernetes objects %s", resource.Spec.ArgoCD.ApplicationFile) } switch resource.Spec.ArgoCD.Type { case argocdapplication.ApplicationKind: app, ok := objs[0].(*argov1alpha1.Application) if !ok { return ctrl.Result{}, fmt.Errorf("object is not an ArgoCD application %s", resource.Spec.ArgoCD.ApplicationFile) } util.SetPackageLabels(app) res, err := r.reconcileArgoCDApp(ctx, resource, app) if err != nil { return ctrl.Result{}, err } foundAppObj := argov1alpha1.Application{} err = r.Client.Get(ctx, client.ObjectKeyFromObject(app), &foundAppObj) if err != nil { if errors.IsNotFound(err) { err = r.Client.Create(ctx, app) if err != nil { return ctrl.Result{}, fmt.Errorf("creating %s app CR: %w", app.Name, err) } return ctrl.Result{RequeueAfter: requeueTime}, nil } return ctrl.Result{}, fmt.Errorf("getting argocd application object: %w", err) } util.SetPackageLabels(&foundAppObj) foundAppObj.Spec = app.Spec foundAppObj.ObjectMeta.Annotations = app.GetAnnotations() foundAppObj.ObjectMeta.Labels = app.GetLabels() err = r.Client.Update(ctx, &foundAppObj) if err != nil { return ctrl.Result{}, fmt.Errorf("updating argocd application object %s: %w", app.Name, err) } return res, nil case argocdapplication.ApplicationSetKind: // application set embeds application spec. extract it then handle git generator repoURLs. appSet, ok := objs[0].(*argov1alpha1.ApplicationSet) if !ok { return ctrl.Result{}, fmt.Errorf("object is not an ArgoCD application set %s", resource.Spec.ArgoCD.ApplicationFile) } util.SetPackageLabels(appSet) res, err := r.reconcileArgoCDAppSet(ctx, resource, appSet) if err != nil { return ctrl.Result{}, err } foundAppSetObj := argov1alpha1.ApplicationSet{} err = r.Client.Get(ctx, client.ObjectKeyFromObject(appSet), &foundAppSetObj) if err != nil { if errors.IsNotFound(err) { err = r.Client.Create(ctx, appSet) if err != nil { return ctrl.Result{}, fmt.Errorf("creating %s argocd application set CR: %w", appSet.Name, err) } return ctrl.Result{RequeueAfter: requeueTime}, nil } return ctrl.Result{}, fmt.Errorf("getting argocd application set object: %w", err) } util.SetPackageLabels(&foundAppSetObj) foundAppSetObj.Spec = appSet.Spec foundAppSetObj.ObjectMeta.Annotations = appSet.GetAnnotations() foundAppSetObj.ObjectMeta.Labels = appSet.GetLabels() err = r.Client.Update(ctx, &foundAppSetObj) if err != nil { return ctrl.Result{}, fmt.Errorf("updating argocd application object %s: %w", appSet.Name, err) } return res, nil default: return ctrl.Result{}, fmt.Errorf("file is not a supported argocd kind %s", resource.Spec.ArgoCD.ApplicationFile) } } func (r *Reconciler) reconcileArgoCDApp(ctx context.Context, resource *v1alpha1.CustomPackage, app *argov1alpha1.Application) (ctrl.Result, error) { appSourcesSynced := true repoRefs := make([]v1alpha1.ObjectRef, 0, 1) if app.Spec.HasMultipleSources() { notSyncedRepos := 0 for j := range app.Spec.Sources { s := &app.Spec.Sources[j] res, sErr := r.reconcileHelmValueObject(ctx, s, resource, app.Name) if sErr != nil { return res, sErr } res, repo, sErr := r.reconcileArgoCDSource(ctx, resource, s.RepoURL, app.Name) if sErr != nil { return res, sErr } if repo != nil { if repo.Status.InternalGitRepositoryUrl == "" { notSyncedRepos += 1 } s.RepoURL = repo.Status.InternalGitRepositoryUrl repoRefs = append(repoRefs, v1alpha1.ObjectRef{ Namespace: repo.Namespace, Name: repo.Name, UID: string(repo.ObjectMeta.UID), }) } } appSourcesSynced = notSyncedRepos == 0 } else { s := app.Spec.Source res, sErr := r.reconcileHelmValueObject(ctx, s, resource, app.Name) if sErr != nil { return res, sErr } res, repo, sErr := r.reconcileArgoCDSource(ctx, resource, s.RepoURL, app.Name) if sErr != nil { return res, sErr } if repo != nil { appSourcesSynced = repo.Status.InternalGitRepositoryUrl != "" s.RepoURL = repo.Status.InternalGitRepositoryUrl repoRefs = append(repoRefs, v1alpha1.ObjectRef{ Namespace: repo.Namespace, Name: repo.Name, UID: string(repo.ObjectMeta.UID), }) } } resource.Status.GitRepositoryRefs = repoRefs resource.Status.Synced = appSourcesSynced // Only requeue if not synced yet to avoid continuous reconciliation if !appSourcesSynced { return ctrl.Result{RequeueAfter: requeueTime}, nil } return ctrl.Result{}, nil } func (r *Reconciler) reconcileArgoCDAppSet(ctx context.Context, resource *v1alpha1.CustomPackage, appSet *argov1alpha1.ApplicationSet) (ctrl.Result, error) { notSyncedRepos := 0 for i := range appSet.Spec.Generators { g := appSet.Spec.Generators[i] if g.Git != nil { res, repo, gErr := r.reconcileArgoCDSource(ctx, resource, g.Git.RepoURL, appSet.GetName()) if gErr != nil { return res, fmt.Errorf("reconciling git generator URL %s, %s: %w", g.Git.RepoURL, resource.Spec.ArgoCD.ApplicationFile, gErr) } if repo != nil { g.Git.RepoURL = repo.Status.InternalGitRepositoryUrl if repo.Status.InternalGitRepositoryUrl == "" { notSyncedRepos += 1 } } } if g.Matrix != nil { for j := range g.Matrix.Generators { nestedGenerator := g.Matrix.Generators[j] if nestedGenerator.Git != nil { res, repo, gErr := r.reconcileArgoCDSource(ctx, resource, nestedGenerator.Git.RepoURL, appSet.GetName()) if gErr != nil { return res, fmt.Errorf("reconciling git generator URL %s, %s: %w", nestedGenerator.Git.RepoURL, resource.Spec.ArgoCD.ApplicationFile, gErr) } if repo != nil { nestedGenerator.Git.RepoURL = repo.Status.InternalGitRepositoryUrl if repo.Status.InternalGitRepositoryUrl == "" { notSyncedRepos += 1 } } } } } } gitGeneratorsSynced := notSyncedRepos == 0 app := argov1alpha1.Application{ ObjectMeta: metav1.ObjectMeta{Name: appSet.GetName(), Namespace: appSet.Namespace}, } app.Spec = appSet.Spec.Template.Spec _, err := r.reconcileArgoCDApp(ctx, resource, &app) if err != nil { return ctrl.Result{}, fmt.Errorf("reconciling application set %s %w", resource.Spec.ArgoCD.ApplicationFile, err) } resource.Status.Synced = resource.Status.Synced && gitGeneratorsSynced // Only requeue if not synced yet to avoid continuous reconciliation if !resource.Status.Synced { return ctrl.Result{RequeueAfter: requeueTime}, nil } return ctrl.Result{}, nil } // create a gitrepository custom resource, then let the git repository controller take care of the rest func (r *Reconciler) reconcileArgoCDSource(ctx context.Context, resource *v1alpha1.CustomPackage, repoUrl, appName string) (ctrl.Result, *v1alpha1.GitRepository, error) { if isCNOEScheme(repoUrl) { if resource.Spec.RemoteRepository.Url == "" { return r.reconcileArgoCDSourceFromLocal(ctx, resource, appName, repoUrl) } return r.reconcileArgoCDSourceFromRemote(ctx, resource, appName, repoUrl) } return ctrl.Result{}, nil, nil } func (r *Reconciler) reconcileArgoCDSourceFromRemote(ctx context.Context, resource *v1alpha1.CustomPackage, appName, repoURL string) (ctrl.Result, *v1alpha1.GitRepository, error) { logger := log.FromContext(ctx) relativePath := strings.TrimPrefix(repoURL, v1alpha1.CNOEURIScheme) // no guarantee that this path exists dirPath := filepath.Join(resource.Spec.RemoteRepository.Path, relativePath) repo := &v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: remoteRepoName(appName, dirPath, resource.Spec.RemoteRepository), Namespace: resource.Namespace, }, } // Check if GitRepository already exists existingRepo := &v1alpha1.GitRepository{} getErr := r.Client.Get(ctx, client.ObjectKeyFromObject(repo), existingRepo) if getErr == nil { // GitRepository exists - check if we should take it over shouldTakeOver, checkErr := r.shouldTakeOverGitRepository(ctx, resource, existingRepo) if checkErr != nil { return ctrl.Result{}, nil, fmt.Errorf("checking if should take over git repository: %w", checkErr) } if !shouldTakeOver { // A higher/equal priority package owns this, just return it without updating logger.V(1).Info("Using existing GitRepository owned by higher priority package", "repo", repo.Name, "ourPriority", resource.ObjectMeta.Annotations[v1alpha1.PackagePriorityAnnotation]) return ctrl.Result{}, existingRepo, nil } // We should take it over - proceed with CreateOrUpdate below } else if !errors.IsNotFound(getErr) { return ctrl.Result{}, nil, getErr } // GitRepository doesn't exist or we should take it over cliStartTime, _ := util.GetCLIStartTimeAnnotationValue(resource.ObjectMeta.Annotations) var err error _, err = controllerutil.CreateOrUpdate(ctx, r.Client, repo, func() error { if err := controllerutil.SetControllerReference(resource, repo, r.Scheme); err != nil { return err } if repo.ObjectMeta.Annotations == nil { repo.ObjectMeta.Annotations = make(map[string]string) } util.SetCLIStartTimeAnnotationValue(repo.ObjectMeta.Annotations, cliStartTime) repo.Spec = v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: v1alpha1.SourceTypeRemote, RemoteRepository: resource.Spec.RemoteRepository, Path: dirPath, }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: resource.Spec.GitServerURL, InternalGitURL: resource.Spec.InternalGitServeURL, OrganizationName: v1alpha1.GiteaAdminUserName, }, SecretRef: resource.Spec.GitServerAuthSecretRef, } return nil }) if err != nil && !errors.IsAlreadyExists(err) { return ctrl.Result{}, nil, err } return ctrl.Result{}, repo, nil } func (r *Reconciler) reconcileArgoCDSourceFromLocal(ctx context.Context, resource *v1alpha1.CustomPackage, appName, repoURL string) (ctrl.Result, *v1alpha1.GitRepository, error) { logger := log.FromContext(ctx) absPath, err := getCNOEAbsPath(resource.Spec.ArgoCD.ApplicationFile, repoURL) if err != nil { logger.Error(err, "processing argocd app source", "dir", resource.Spec.ArgoCD.ApplicationFile, "repoURL", repoURL) return ctrl.Result{}, nil, err } repo := &v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName(appName, absPath), Namespace: resource.Namespace, }, } // Check if GitRepository already exists existingRepo := &v1alpha1.GitRepository{} getErr := r.Client.Get(ctx, client.ObjectKeyFromObject(repo), existingRepo) if getErr == nil { // GitRepository exists - check if we should take it over shouldTakeOver, checkErr := r.shouldTakeOverGitRepository(ctx, resource, existingRepo) if checkErr != nil { return ctrl.Result{}, nil, fmt.Errorf("checking if should take over git repository: %w", checkErr) } if !shouldTakeOver { // A higher/equal priority package owns this, just return it without updating logger.V(1).Info("Using existing GitRepository owned by higher priority package", "repo", repo.Name, "ourPriority", resource.ObjectMeta.Annotations[v1alpha1.PackagePriorityAnnotation]) return ctrl.Result{}, existingRepo, nil } // We should take it over - proceed with CreateOrUpdate below } else if !errors.IsNotFound(getErr) { return ctrl.Result{}, nil, getErr } // GitRepository doesn't exist or we should take it over cliStartTime, _ := util.GetCLIStartTimeAnnotationValue(resource.ObjectMeta.Annotations) _, err = controllerutil.CreateOrUpdate(ctx, r.Client, repo, func() error { if err := controllerutil.SetControllerReference(resource, repo, r.Scheme); err != nil { return err } if repo.ObjectMeta.Annotations == nil { repo.ObjectMeta.Annotations = make(map[string]string) } util.SetCLIStartTimeAnnotationValue(repo.ObjectMeta.Annotations, cliStartTime) repo.Spec = v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: v1alpha1.SourceTypeLocal, Path: absPath, }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: resource.Spec.GitServerURL, InternalGitURL: resource.Spec.InternalGitServeURL, OrganizationName: v1alpha1.GiteaAdminUserName, }, SecretRef: resource.Spec.GitServerAuthSecretRef, } return nil }) // it's possible for an application to specify the same directory multiple times in the spec. // if there is a repository already created for this package, no further action is necessary. if !errors.IsAlreadyExists(err) { return ctrl.Result{}, repo, err } return ctrl.Result{}, repo, nil } func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.CustomPackage{}). Complete(r) } func (r *Reconciler) getArgoCDAppFile(ctx context.Context, resource *v1alpha1.CustomPackage) ([]byte, error) { filePath := resource.Spec.ArgoCD.ApplicationFile if resource.Spec.RemoteRepository.Url == "" { return os.ReadFile(filePath) } cloneDir := util.RepoDir(resource.Spec.RemoteRepository.Url, r.TempDir) st := r.RepoMap.LoadOrStore(resource.Spec.RemoteRepository.Url, cloneDir) st.MU.Lock() wt, _, err := util.CloneRemoteRepoToDir(ctx, resource.Spec.RemoteRepository, 1, false, cloneDir, "") defer st.MU.Unlock() if err != nil { return nil, fmt.Errorf("cloning repo, %s: %w", resource.Spec.RemoteRepository.Url, err) } return util.ReadWorktreeFile(wt, filePath) } func (r *Reconciler) reconcileHelmValueObject(ctx context.Context, source *argov1alpha1.ApplicationSource, resource *v1alpha1.CustomPackage, appName string, ) (ctrl.Result, error) { if source.Helm == nil || source.Helm.ValuesObject == nil { return ctrl.Result{}, nil } var data any err := json.Unmarshal(source.Helm.ValuesObject.Raw, &data) if err != nil { return ctrl.Result{}, fmt.Errorf("processing helm valuesObject: %w", err) } res, err := r.reconcileHelmValueObjectSource(ctx, &data, resource, appName) if err != nil { return ctrl.Result{}, err } raw, err := json.Marshal(data) if err != nil { return ctrl.Result{}, fmt.Errorf("converting helm valuesObject to json") } source.Helm.ValuesObject.Raw = raw return res, nil } func (r *Reconciler) reconcileHelmValueObjectSource(ctx context.Context, valueObject *any, resource *v1alpha1.CustomPackage, appName string, ) (ctrl.Result, error) { switch val := (*valueObject).(type) { case string: res, repo, err := r.reconcileArgoCDSource(ctx, resource, val, appName) if err != nil { return res, fmt.Errorf("processing %s in helmValueObject: %w", val, err) } if repo != nil { *valueObject = repo.Status.InternalGitRepositoryUrl } case map[string]any: for k := range val { v := val[k] res, err := r.reconcileHelmValueObjectSource(ctx, &v, resource, appName) if err != nil { return res, err } val[k] = v } case []any: for k := range val { v := val[k] res, err := r.reconcileHelmValueObjectSource(ctx, &v, resource, appName) if err != nil { return res, err } val[k] = v } } // No need to requeue for helm value processing return ctrl.Result{}, nil } func localRepoName(appName, dir string) string { return fmt.Sprintf("%s-%s", appName, filepath.Base(dir)) } func remoteRepoName(appName, pathToPkg string, repo v1alpha1.RemoteRepositorySpec) string { return fmt.Sprintf("%s-%s", appName, filepath.Base(pathToPkg)) } func isCNOEScheme(repoURL string) bool { return strings.HasPrefix(repoURL, v1alpha1.CNOEURIScheme) } func getCNOEAbsPath(fPath, repoURL string) (string, error) { parentDir := filepath.Dir(fPath) relativePath := strings.TrimPrefix(repoURL, v1alpha1.CNOEURIScheme) absPath, err := filepath.Abs(filepath.Join(parentDir, relativePath)) if err != nil { return "", err } f, err := os.Stat(absPath) if err != nil { return "", err } if !f.IsDir() { return "", fmt.Errorf("path not a directory: %s", absPath) } return absPath, err } ================================================ FILE: pkg/controllers/custompackage/controller_test.go ================================================ package custompackage import ( "context" "fmt" "os" "path/filepath" "reflect" "runtime" "strings" "testing" "time" argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sruntime "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" ) type testCase struct { expectedGitRepo v1alpha1.GitRepository expectedApplicationSet argov1alpha1.ApplicationSet input v1alpha1.CustomPackage } func TestReconcileCustomPkg(t *testing.T) { s := k8sruntime.NewScheme() sb := k8sruntime.NewSchemeBuilder( v1.AddToScheme, argov1alpha1.AddToScheme, v1alpha1.AddToScheme, ) sb.AddToScheme(s) testEnv := &envtest.Environment{ CRDDirectoryPaths: []string{ filepath.Join("..", "resources"), "../localbuild/resources/argo/install.yaml", }, ErrorIfCRDPathMissing: true, Scheme: s, BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", fmt.Sprintf("1.29.1-%s-%s", runtime.GOOS, runtime.GOARCH)), } cfg, err := testEnv.Start() require.NoError(t, err) defer testEnv.Stop() mgr, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: s, }) require.NoError(t, err) ctx, ctxCancel := context.WithCancel(context.Background()) stoppedCh := make(chan error) go func() { err := mgr.Start(ctx) stoppedCh <- err }() defer func() { ctxCancel() err := <-stoppedCh if err != nil { t.Errorf("Starting controller manager: %v", err) t.FailNow() } }() r := &Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("test-custompkg-controller"), } cwd, err := os.Getwd() require.NoError(t, err) customPkgs := []v1alpha1.CustomPackage{ { ObjectMeta: metav1.ObjectMeta{ Name: "test1", Namespace: "test", UID: "abc", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/testDir/app.yaml"), Name: "my-app", Namespace: "argocd", Type: "Application", }, }, }, { ObjectMeta: metav1.ObjectMeta{ Name: "test2", Namespace: "test", UID: "abc", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: false, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://cnoe.io/internal", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/testDir2/exampleApp.yaml"), Name: "guestbook", Namespace: "argocd", Type: "Application", }, }, }, { ObjectMeta: metav1.ObjectMeta{ Name: "test3", Namespace: "test", UID: "abc", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/testDir/app2.yaml"), Name: "my-app2", Namespace: "argocd", Type: "Application", }, }, }, } for _, n := range []string{"argocd", "test"} { ns := v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: n, }, } err = mgr.GetClient().Create(context.Background(), &ns) if err != nil { t.Fatalf("creating test ns: %v", err) } } for i := range customPkgs { _, err = r.reconcileCustomPackage(context.Background(), &customPkgs[i]) if err != nil { t.Fatalf("reconciling custom packages %v", err) } } time.Sleep(1 * time.Second) // verify repo. c := mgr.GetClient() repo := v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName("my-app", "test/resources/customPackages/testDir/app1"), Namespace: "test", }, } err = c.Get(context.Background(), client.ObjectKeyFromObject(&repo), &repo) if err != nil { t.Fatalf("getting my-app-app1 git repo %v", err) } p, _ := filepath.Abs("test/resources/customPackages/testDir/app1") expectedRepo := v1alpha1.GitRepository{ Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: "local", Path: p, }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: "https://cnoe.io", InternalGitURL: "http://internal.cnoe.io", OrganizationName: v1alpha1.GiteaAdminUserName, }, }, } assert.Equal(t, repo.Spec, expectedRepo.Spec) ok := reflect.DeepEqual(repo.Spec, expectedRepo.Spec) assert.True(t, ok) tcs := []struct { name string }{ { name: "my-app", }, { name: "my-app2", }, { name: "guestbook", }, } for _, tc := range tcs { app := argov1alpha1.Application{ ObjectMeta: metav1.ObjectMeta{ Name: tc.name, Namespace: "argocd", }, } err = c.Get(context.Background(), client.ObjectKeyFromObject(&app), &app) assert.NoError(t, err) if app.ObjectMeta.Labels == nil { t.Fatalf("labels not set") } _, ok := app.ObjectMeta.Labels[v1alpha1.PackageNameLabelKey] if !ok { t.Fatalf("label %s not set", v1alpha1.PackageTypeLabelKey) } _, ok = app.ObjectMeta.Labels[v1alpha1.PackageNameLabelKey] if !ok { t.Fatalf("label %s not set", v1alpha1.PackageNameLabelKey) } if app.Spec.Sources == nil { if strings.HasPrefix(app.Spec.Source.RepoURL, v1alpha1.CNOEURIScheme) { t.Fatalf("%s prefix should be removed", v1alpha1.CNOEURIScheme) } continue } for _, s := range app.Spec.Sources { if strings.HasPrefix(s.RepoURL, v1alpha1.CNOEURIScheme) { t.Fatalf("%s prefix should be removed", v1alpha1.CNOEURIScheme) } } } } func TestReconcileCustomPkgAppSet(t *testing.T) { s := k8sruntime.NewScheme() sb := k8sruntime.NewSchemeBuilder( v1.AddToScheme, argov1alpha1.AddToScheme, v1alpha1.AddToScheme, ) sb.AddToScheme(s) testEnv := &envtest.Environment{ CRDDirectoryPaths: []string{ filepath.Join("..", "resources"), "../localbuild/resources/argo/install.yaml", }, ErrorIfCRDPathMissing: true, Scheme: s, BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", fmt.Sprintf("1.29.1-%s-%s", runtime.GOOS, runtime.GOARCH)), } cfg, err := testEnv.Start() assert.Nil(t, err) defer testEnv.Stop() mgr, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: s, }) assert.Nil(t, err) ctx, ctxCancel := context.WithCancel(context.Background()) stoppedCh := make(chan error) go func() { err := mgr.Start(ctx) stoppedCh <- err }() defer func() { ctxCancel() err := <-stoppedCh if err != nil { t.Errorf("Starting controller manager: %v", err) t.FailNow() } }() r := &Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("test-custompkg-controller"), } cwd, err := os.Getwd() assert.Nil(t, err) for _, n := range []string{"argocd", "test"} { ns := v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: n, }, } err = mgr.GetClient().Create(context.Background(), &ns) assert.Nil(t, err) } cases := []testCase{ { input: v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "test1", Namespace: "test", UID: "abc", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/applicationSet/generator-single-source.yaml"), Type: "ApplicationSet", }, }, }, expectedGitRepo: v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName("generator-single-source", "test/resources/customPackages/applicationSet/test1"), Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: "local", Path: filepath.Join(cwd, "test/resources/customPackages/applicationSet/test1"), }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: "https://cnoe.io", InternalGitURL: "http://internal.cnoe.io", OrganizationName: v1alpha1.GiteaAdminUserName, }, }, }, expectedApplicationSet: argov1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "generator-single-source", Namespace: "argocd", }, Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{ { Git: &argov1alpha1.GitGenerator{ RepoURL: "", }, }, }, Template: argov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Source: &argov1alpha1.ApplicationSource{ RepoURL: "", }, }, }, }, }, }, { input: v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "test2", Namespace: "test", UID: "test2", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/applicationSet/generator-multi-sources.yaml"), Type: "ApplicationSet", }, }, }, expectedGitRepo: v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName("generator-multi-sources", "test/resources/customPackages/applicationSet/test1"), Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: "local", Path: filepath.Join(cwd, "test/resources/customPackages/applicationSet/test1"), }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: "https://cnoe.io", InternalGitURL: "http://internal.cnoe.io", OrganizationName: v1alpha1.GiteaAdminUserName, }, }, }, expectedApplicationSet: argov1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "generator-multi-sources", Namespace: "argocd", }, Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{ { Git: &argov1alpha1.GitGenerator{ RepoURL: "", }, }, }, Template: argov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Sources: []argov1alpha1.ApplicationSource{ { RepoURL: "", }, }, }, }, }, }, }, { input: v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "test3", Namespace: "test", UID: "test3", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/applicationSet/no-generator-single-source.yaml"), Type: "ApplicationSet", }, }, }, expectedGitRepo: v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName("no-generator-single-source", "test/resources/customPackages/applicationSet/test1"), Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: "local", Path: filepath.Join(cwd, "test/resources/customPackages/applicationSet/test1"), }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: "https://cnoe.io", InternalGitURL: "http://internal.cnoe.io", OrganizationName: v1alpha1.GiteaAdminUserName, }, }, }, expectedApplicationSet: argov1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "no-generator-single-source", Namespace: "argocd", }, Spec: argov1alpha1.ApplicationSetSpec{ Template: argov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Source: &argov1alpha1.ApplicationSource{ RepoURL: "", }, }, }, }, }, }, { input: v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "test4", Namespace: "test", UID: "test4", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/applicationSet/generator-matrix.yaml"), Type: "ApplicationSet", }, }, }, expectedGitRepo: v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: localRepoName("generator-matrix", "test/resources/customPackages/applicationSet/test1"), Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: "local", Path: filepath.Join(cwd, "test/resources/customPackages/applicationSet/test1"), }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: "https://cnoe.io", InternalGitURL: "http://internal.cnoe.io", OrganizationName: v1alpha1.GiteaAdminUserName, }, }, }, expectedApplicationSet: argov1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "generator-matrix", Namespace: "argocd", }, Spec: argov1alpha1.ApplicationSetSpec{ Generators: []argov1alpha1.ApplicationSetGenerator{ { Matrix: &argov1alpha1.MatrixGenerator{ Generators: []argov1alpha1.ApplicationSetNestedGenerator{ { Git: &argov1alpha1.GitGenerator{ RepoURL: "", }, }, }, }, }, }, Template: argov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Source: &argov1alpha1.ApplicationSource{ RepoURL: "", }, }, }, }, }, }, } for i := range cases { tc := cases[i] _, err = r.reconcileCustomPackage(context.Background(), &tc.input) assert.Nil(t, err) time.Sleep(1 * time.Second) c := mgr.GetClient() repo := v1alpha1.GitRepository{} err = c.Get(context.Background(), client.ObjectKeyFromObject(&tc.expectedGitRepo), &repo) assert.Nil(t, err) assert.Equal(t, tc.expectedGitRepo.Spec, repo.Spec) // verify argocd applicationSet appset := argov1alpha1.ApplicationSet{} err = c.Get(context.Background(), client.ObjectKeyFromObject(&tc.expectedApplicationSet), &appset) assert.Nil(t, err) if len(tc.expectedApplicationSet.Spec.Template.Spec.Sources) > 0 { for j := range tc.expectedApplicationSet.Spec.Template.Spec.Sources { exs := tc.expectedApplicationSet.Spec.Template.Spec.Sources[j] assert.Equal(t, exs.RepoURL, appset.Spec.Template.Spec.Sources[j].RepoURL) assert.False(t, strings.HasPrefix(appset.Spec.Template.Spec.Sources[j].RepoURL, v1alpha1.CNOEURIScheme)) } } else { assert.Equal(t, tc.expectedApplicationSet.Spec.Template.Spec.Source.RepoURL, appset.Spec.Template.Spec.Source.RepoURL) assert.False(t, strings.HasPrefix(appset.Spec.Template.Spec.Source.RepoURL, v1alpha1.CNOEURIScheme)) } if len(tc.expectedApplicationSet.Spec.Generators) > 0 { for j := range tc.expectedApplicationSet.Spec.Generators { exg := tc.expectedApplicationSet.Spec.Generators[j] if exg.Git != nil { assert.Equal(t, exg.Git.RepoURL, appset.Spec.Generators[j].Git.RepoURL) } if exg.Matrix != nil { for k := range exg.Matrix.Generators { if exg.Matrix.Generators[k].Git != nil { assert.Equal(t, exg.Matrix.Generators[k].Git.RepoURL, appset.Spec.Generators[j].Matrix.Generators[k].Git.RepoURL) } } } } } } } func TestReconcileHelmValueObject(t *testing.T) { s := k8sruntime.NewScheme() sb := k8sruntime.NewSchemeBuilder( v1.AddToScheme, argov1alpha1.AddToScheme, v1alpha1.AddToScheme, ) sb.AddToScheme(s) testEnv := &envtest.Environment{ CRDDirectoryPaths: []string{ filepath.Join("..", "resources"), "../localbuild/resources/argo/install.yaml", }, ErrorIfCRDPathMissing: true, Scheme: s, BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", fmt.Sprintf("1.29.1-%s-%s", runtime.GOOS, runtime.GOARCH)), } cfg, err := testEnv.Start() if err != nil { t.Fatalf("Starting testenv: %v", err) } defer testEnv.Stop() mgr, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: s, }) if err != nil { t.Fatalf("getting manager: %v", err) } ctx, ctxCancel := context.WithCancel(context.Background()) stoppedCh := make(chan error) go func() { err := mgr.Start(ctx) stoppedCh <- err }() defer func() { ctxCancel() err := <-stoppedCh if err != nil { t.Errorf("Starting controller manager: %v", err) t.FailNow() } }() time.Sleep(1 * time.Second) for _, n := range []string{"argocd", "test"} { ns := v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: n, }, } err = mgr.GetClient().Create(context.Background(), &ns) if err != nil { t.Fatalf("creating test ns: %v", err) } } r := &Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("test-custompkg-controller"), } cwd, _ := os.Getwd() resource := v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "test1", Namespace: "test", UID: "abc", }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/helm/app.yaml"), Name: "my-app", Namespace: "argocd", Type: "Application", }, }, } source := &argov1alpha1.ApplicationSource{ Helm: &argov1alpha1.ApplicationSourceHelm{ ValuesObject: &k8sruntime.RawExtension{ Raw: []byte(`{ "repoURLGit": "cnoe://test", "nested": { "repoURLGit": "cnoe://test", "bool": true, "int": 123 }, "bool": false, "int": 456, "arrayString": [ "abc", "cnoe://test" ], "arrayMap": [ { "test": "cnoe://test", "nested": { "test": "cnoe://test" } } ] }`), }, }, } _, err = r.reconcileHelmValueObject(ctx, source, &resource, "test") assert.NoError(t, err) expectJson := `{"arrayMap":[{"nested":{"test":""},"test":""}],"arrayString":["abc",""],"bool":false,"int":456,"nested":{"bool":true,"int":123,"repoURLGit":""},"repoURLGit":""}` assert.JSONEq(t, expectJson, string(source.Helm.ValuesObject.Raw)) } func TestPackagePriority(t *testing.T) { s := k8sruntime.NewScheme() sb := k8sruntime.NewSchemeBuilder( v1.AddToScheme, argov1alpha1.AddToScheme, v1alpha1.AddToScheme, ) sb.AddToScheme(s) testEnv := &envtest.Environment{ CRDDirectoryPaths: []string{ filepath.Join("..", "resources"), "../localbuild/resources/argo/install.yaml", }, ErrorIfCRDPathMissing: true, Scheme: s, BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", fmt.Sprintf("1.29.1-%s-%s", runtime.GOOS, runtime.GOARCH)), } cfg, err := testEnv.Start() require.NoError(t, err) defer testEnv.Stop() mgr, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: s, }) require.NoError(t, err) ctx, ctxCancel := context.WithCancel(context.Background()) stoppedCh := make(chan error) go func() { err := mgr.Start(ctx) stoppedCh <- err }() defer func() { ctxCancel() err := <-stoppedCh if err != nil { t.Errorf("Starting controller manager: %v", err) t.FailNow() } }() r := &Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("test-custompkg-controller"), } cwd, err := os.Getwd() require.NoError(t, err) // Create namespaces for _, n := range []string{"argocd", "test"} { ns := v1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: n, }, } err = mgr.GetClient().Create(context.Background(), &ns) if err != nil { t.Fatalf("creating test ns: %v", err) } } // Create two CustomPackages with the same app name but different priorities // Package 1 has priority 0 (from first --package argument) pkg1 := v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "pkg1-my-app", Namespace: "test", UID: "pkg1", Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "0", v1alpha1.PackageSourcePathAnnotation: "/path/to/package1", }, }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/testDir/app.yaml"), Name: "my-app", Namespace: "argocd", Type: "Application", }, }, } // Package 2 has priority 1 (from second --package argument, should win) pkg2 := v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: "pkg2-my-app", Namespace: "test", UID: "pkg2", Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "1", v1alpha1.PackageSourcePathAnnotation: "/path/to/package2", }, }, Spec: v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: "https://cnoe.io", InternalGitServeURL: "http://internal.cnoe.io", ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filepath.Join(cwd, "test/resources/customPackages/testDir/app.yaml"), Name: "my-app", Namespace: "argocd", Type: "Application", }, }, } // Create the CustomPackages in the cluster err = mgr.GetClient().Create(context.Background(), &pkg1) require.NoError(t, err) err = mgr.GetClient().Create(context.Background(), &pkg2) require.NoError(t, err) // Test priority resolution t.Run("lower priority package should not reconcile", func(t *testing.T) { shouldReconcile, err := r.shouldReconcile(context.Background(), &pkg1) assert.NoError(t, err) assert.False(t, shouldReconcile, "pkg1 (priority 0) should not reconcile when pkg2 (priority 1) exists") }) t.Run("higher priority package should reconcile", func(t *testing.T) { shouldReconcile, err := r.shouldReconcile(context.Background(), &pkg2) assert.NoError(t, err) assert.True(t, shouldReconcile, "pkg2 (priority 1) should reconcile as it has highest priority") }) t.Run("getPackagePriority should extract priority correctly", func(t *testing.T) { priority1, err := getPackagePriority(&pkg1) assert.NoError(t, err) assert.Equal(t, 0, priority1) priority2, err := getPackagePriority(&pkg2) assert.NoError(t, err) assert.Equal(t, 1, priority2) }) } func TestGetPackagePriority(t *testing.T) { t.Run("valid priority annotation", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "5", }, }, } priority, err := getPackagePriority(pkg) assert.NoError(t, err) assert.Equal(t, 5, priority) }) t.Run("missing annotations", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{}, } _, err := getPackagePriority(pkg) assert.Error(t, err) }) t.Run("missing priority annotation", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ "other": "value", }, }, } _, err := getPackagePriority(pkg) assert.Error(t, err) }) t.Run("invalid priority format", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "invalid", }, }, } _, err := getPackagePriority(pkg) assert.Error(t, err) }) t.Run("zero priority", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "0", }, }, } priority, err := getPackagePriority(pkg) assert.NoError(t, err) assert.Equal(t, 0, priority) }) t.Run("large priority value", func(t *testing.T) { pkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ v1alpha1.PackagePriorityAnnotation: "1000", }, }, } priority, err := getPackagePriority(pkg) assert.NoError(t, err) assert.Equal(t, 1000, priority) }) } ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/generator-matrix.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: generator-matrix namespace: argocd spec: goTemplate: true goTemplateOptions: - missingkey=error generators: - matrix: generators: - git: repoURL: "cnoe://test1" revision: HEAD files: - path: "**/config.yaml" template: metadata: name: "{{ .name }}" labels: environment: "{{ .environment }}" spec: project: default source: repoURL: "cnoe://test1" targetRevision: HEAD path: "{{ .manifestPath }}/manifests" destination: server: https://kubernetes.default.svc namespace: "{{ .namespace }}" syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/generator-multi-sources.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: generator-multi-sources namespace: argocd spec: generators: - git: repoURL: cnoe://test1 revision: HEAD directories: - path: apps/* template: metadata: name: '{{path.basename}}' spec: project: default sources: - repoURL: cnoe://test1 targetRevision: HEAD path: '{{path}}' destination: server: https://kubernetes.default.svc namespace: '{{path.basename}}' syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/generator-single-source.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: generator-single-source namespace: argocd spec: generators: - git: repoURL: cnoe://test1 revision: HEAD directories: - path: apps/* template: metadata: name: '{{path.basename}}' spec: project: default source: repoURL: cnoe://test1 targetRevision: HEAD path: '{{path}}' destination: server: https://kubernetes.default.svc namespace: '{{path.basename}}' syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/no-generator-single-source.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: no-generator-single-source namespace: argocd spec: generators: - clusters: { } template: metadata: name: '{{path.basename}}' spec: project: default source: repoURL: cnoe://test1 targetRevision: HEAD path: '{{path}}' destination: server: https://kubernetes.default.svc namespace: '{{path.basename}}' syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook/guestbook-ui-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: guestbook-ui spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: guestbook-ui template: metadata: labels: app: guestbook-ui spec: containers: - image: gcr.io/heptio-images/ks-guestbook-demo:0.2 name: guestbook-ui ports: - containerPort: 80 ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook/guestbook-ui-svc.yaml ================================================ apiVersion: v1 kind: Service metadata: name: guestbook-ui spec: ports: - port: 80 targetPort: 80 selector: app: guestbook-ui ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook/kustomization.yaml ================================================ namePrefix: kustomize- resources: - guestbook-ui-deployment.yaml - guestbook-ui-svc.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook2/guestbook-ui-deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: guestbook-ui spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app: guestbook-ui template: metadata: labels: app: guestbook-ui spec: containers: - image: gcr.io/heptio-images/ks-guestbook-demo:0.2 name: guestbook-ui ports: - containerPort: 80 ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook2/guestbook-ui-svc.yaml ================================================ apiVersion: v1 kind: Service metadata: name: guestbook-ui spec: ports: - port: 80 targetPort: 80 selector: app: guestbook-ui ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/applicationSet/test1/apps/guestbook2/kustomization.yaml ================================================ namePrefix: kustomize- resources: - guestbook-ui-deployment.yaml - guestbook-ui-svc.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/helm/app.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: my-app-helm namespace: argocd spec: destination: namespace: my-app-helm server: "https://kubernetes.default.svc" source: repoURL: cnoe://test targetRevision: HEAD path: "." helm: valuesObject: repoURLGit: cnoe://test nested: repoURLGit: cnoe://test project: default syncPolicy: automated: selfHeal: true syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/helm/test/Chart.yaml ================================================ apiVersion: v2 name: test description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. # # Application charts are a collection of templates that can be packaged into versioned archives # to be deployed. # # Library charts provide useful utilities or functions for the chart developer. They're included as # a dependency of application charts to inject those utilities and functions into the rendering # pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "1.16.0" ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/helm/test/templates/cm.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: config data: test1: "one" ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/helm/test/values.yaml ================================================ some: value ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir/app.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: my-app namespace: argocd spec: destination: namespace: my-app server: "https://kubernetes.default.svc" source: repoURL: cnoe://app1 targetRevision: HEAD path: "." project: default syncPolicy: automated: selfHeal: true syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir/app1/cm.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: config data: test1: "one" ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir/app2/one/cm.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: one-config data: test1: "one" ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir/app2/two/cm.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: two-config data: test1: "one" ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir/app2.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: my-app2 namespace: argocd spec: destination: namespace: my-app2 server: "https://kubernetes.default.svc" sources: - repoURL: cnoe://app2 targetRevision: HEAD path: "one" - repoURL: cnoe://app2 targetRevision: HEAD path: "two" project: default syncPolicy: automated: selfHeal: true syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir2/exampleApp.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: guestbook namespace: argocd spec: project: default source: repoURL: https://github.com/argoproj/argocd-example-apps.git targetRevision: HEAD path: guestbook destination: server: https://kubernetes.default.svc namespace: guestbook syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/custompackage/test/resources/customPackages/testDir2/exampleApp2.yaml ================================================ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: guestbook2 namespace: argocd spec: project: default source: repoURL: https://github.com/argoproj/argocd-example-apps.git targetRevision: HEAD path: guestbook destination: server: https://kubernetes.default.svc namespace: guestbook2 syncPolicy: syncOptions: - CreateNamespace=true ================================================ FILE: pkg/controllers/doc.go ================================================ package controllers ================================================ FILE: pkg/controllers/gitrepository/controller.go ================================================ package gitrepository import ( "context" "errors" "fmt" "net" "net/http" "time" "code.gitea.io/sdk/gitea" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" gitclient "github.com/go-git/go-git/v5/plumbing/transport/client" githttp "github.com/go-git/go-git/v5/plumbing/transport/http" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/log" ) const ( DefaultBranchName = "main" requeueTime = time.Second * 30 gitCommitAuthorName = "git-reconciler" gitCommitAuthorEmail = "idpbuilder-agent@cnoe.io" gitTCPTimeout = 5 * time.Second // timeout value for a git operation through http. clone, push, etc. gitHTTPTimeout = 30 * time.Second ) func init() { configureGitClient() } type RepositoryReconciler struct { client.Client Recorder record.EventRecorder Scheme *runtime.Scheme Config v1alpha1.BuildCustomizationSpec GitProviderFunc gitProviderFunc TempDir string RepoMap *util.RepoMap } type gitProviderFunc func(context.Context, *v1alpha1.GitRepository, client.Client, *runtime.Scheme, v1alpha1.BuildCustomizationSpec) (gitProvider, error) type notFoundError struct{} func (n notFoundError) Error() string { return fmt.Sprintf("repo not found") } func getRepositoryName(repo v1alpha1.GitRepository) string { return fmt.Sprintf("%s-%s", repo.Namespace, repo.Name) } func getOrganizationName(repo v1alpha1.GitRepository) string { return repo.Spec.Provider.OrganizationName } func getFallbackRepositoryURL(repo *v1alpha1.GitRepository, info repoInfo) string { return fmt.Sprintf("%s/%s.git", repo.Spec.Provider.GitURL, info.fullName) } func GetGitProvider(ctx context.Context, repo *v1alpha1.GitRepository, kubeClient client.Client, scheme *runtime.Scheme, tmplConfig v1alpha1.BuildCustomizationSpec) (gitProvider, error) { switch repo.Spec.Provider.Name { case v1alpha1.GitProviderGitea: giteaClient, err := NewGiteaClient(repo.Spec.Provider.GitURL, gitea.SetHTTPClient(util.GetHttpClient())) if err != nil { return nil, err } return &giteaProvider{ Client: kubeClient, Scheme: scheme, giteaClient: giteaClient, config: tmplConfig, }, nil case v1alpha1.GitProviderGitHub: return &gitHubProvider{ Client: kubeClient, Scheme: scheme, config: tmplConfig, gitHubClient: newGitHubClient(nil), }, nil } return nil, fmt.Errorf("invalid git provider %s ", repo.Spec.Provider.Name) } func (r *RepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx) var gitRepo v1alpha1.GitRepository err := r.Get(ctx, req.NamespacedName, &gitRepo) if err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } defer r.postProcessReconcile(ctx, req, &gitRepo) logger.V(1).Info("reconciling GitRepository", "name", req.Name, "namespace", req.Namespace) result, err := r.reconcileGitRepo(ctx, &gitRepo) if err != nil { r.Recorder.Event(&gitRepo, "Warning", "reconcile error", err.Error()) } else { r.Recorder.Event(&gitRepo, "Normal", "reconcile success", "Successfully reconciled") } return result, err } func (r *RepositoryReconciler) postProcessReconcile(ctx context.Context, req ctrl.Request, repo *v1alpha1.GitRepository) { logger := log.FromContext(ctx) err := r.Status().Update(ctx, repo) if err != nil { logger.Error(err, "failed updating repo status") } err = util.UpdateSyncAnnotation(ctx, r.Client, repo) if err != nil { logger.Error(err, "failed updating repo annotation") } } func (r *RepositoryReconciler) reconcileGitRepo(ctx context.Context, repo *v1alpha1.GitRepository) (ctrl.Result, error) { logger := log.FromContext(ctx) logger.V(1).Info("reconciling", "name", repo.Name, "dir", repo.Spec.Source) repo.Status.Synced = false provider, err := r.GitProviderFunc(ctx, repo, r.Client, r.Scheme, r.Config) if err != nil { return ctrl.Result{}, fmt.Errorf("initializing git provider: %w", err) } creds, err := provider.getProviderCredentials(ctx, repo) if err != nil { return ctrl.Result{}, fmt.Errorf("getting git provider credentials: %w", err) } if r.Config.StaticPassword { creds.password = util.StaticPassword } err = provider.setProviderCredentials(ctx, repo, creds) if err != nil { return ctrl.Result{}, fmt.Errorf("setting git provider credentials: %w", err) } var providerRepo repoInfo p, err := provider.getRepository(ctx, repo) if err != nil { if errors.Is(err, notFoundError{}) { p, err = provider.createRepository(ctx, repo) if err != nil { return ctrl.Result{}, fmt.Errorf("creating repository: %w", err) } providerRepo = p } else { return ctrl.Result{}, fmt.Errorf("getting repository: %w", err) } } else { providerRepo = p } err = provider.updateRepoContent(ctx, repo, providerRepo, creds, r.TempDir, r.RepoMap) if err != nil { return ctrl.Result{}, fmt.Errorf("updating repository contents: %w", err) } repo.Status.ExternalGitRepositoryUrl = providerRepo.cloneUrl repo.Status.InternalGitRepositoryUrl = providerRepo.internalGitRepositoryUrl repo.Status.Synced = true // Keep requeueing to detect source file changes, but addAllAndCommit // already checks if there are changes before pushing return ctrl.Result{Requeue: true, RequeueAfter: requeueTime}, nil } func (r *RepositoryReconciler) SetupWithManager(mgr ctrl.Manager, notifyChan chan event.GenericEvent) error { // TODO: should use notifyChan to trigger reconcile when FS changes return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.GitRepository{}). Complete(r) } func addAllAndCommit(path string, gitRepo *git.Repository) (plumbing.Hash, bool, error) { tree, err := gitRepo.Worktree() if err != nil { return plumbing.Hash{}, false, fmt.Errorf("getting git worktree: %w", err) } err = tree.AddGlob("*") if err != nil { return plumbing.Hash{}, false, fmt.Errorf("adding git files: %w", err) } status, err := tree.Status() if err != nil { return plumbing.Hash{}, false, fmt.Errorf("getting git status: %w", err) } if status.IsClean() { h, _ := gitRepo.Head() return h.Hash(), false, nil } h, err := tree.Commit(fmt.Sprintf("updated from %s", path), &git.CommitOptions{ All: true, AllowEmptyCommits: false, Author: &object.Signature{ Name: gitCommitAuthorName, Email: gitCommitAuthorEmail, When: time.Now(), }, }) return h, true, nil } func pushToRemote(ctx context.Context, remoteRepo *git.Repository, creds gitProviderCredentials) error { auth, err := getBasicAuth(creds) if err != nil { return fmt.Errorf("getting basic auth: %w", err) } return remoteRepo.PushContext(ctx, &git.PushOptions{ Auth: &auth, InsecureSkipTLS: true, }) } // add files from local fs to target repository (gitea for now) func reconcileLocalRepoContent(ctx context.Context, repo *v1alpha1.GitRepository, tgtRepo repoInfo, creds gitProviderCredentials, scheme *runtime.Scheme, tmplConfig v1alpha1.BuildCustomizationSpec, tmpDir string, repoMap *util.RepoMap) error { logger := log.FromContext(ctx) tgtCloneDir := util.RepoDir(tgtRepo.cloneUrl, tmpDir) st := repoMap.LoadOrStore(tgtRepo.cloneUrl, tgtCloneDir) st.MU.Lock() defer st.MU.Unlock() tgtRepoSpec := v1alpha1.RemoteRepositorySpec{ CloneSubmodules: false, Path: ".", Url: tgtRepo.cloneUrl, Ref: "", } logger.V(1).Info("cloning repo", "repoUrl", tgtRepoSpec.Url, "fallbackUrl", getFallbackRepositoryURL(repo, tgtRepo), "cloneDir", tgtCloneDir) _, tgtRepository, err := util.CloneRemoteRepoToDir(ctx, tgtRepoSpec, 1, true, tgtCloneDir, getFallbackRepositoryURL(repo, tgtRepo)) if err != nil { return fmt.Errorf("cloning repo %s: %w", tgtRepoSpec.Url, err) } err = writeRepoContents(repo, tgtCloneDir, tmplConfig, scheme) if err != nil { return fmt.Errorf("writing repo contents: %w", err) } hash, push, err := addAllAndCommit(repo.Spec.Source.Path, tgtRepository) if err != nil { return fmt.Errorf("add and commit %w", err) } if push { remoteUrl, err := util.FirstRemoteURL(tgtRepository) if err != nil { return fmt.Errorf("getting remote url %w", err) } logger.V(1).Info("pushing to remote url", "remoteUrl", remoteUrl) err = pushToRemote(ctx, tgtRepository, creds) if err != nil { return fmt.Errorf("pushing to git: %w", err) } repo.Status.LatestCommit.Hash = hash.String() return nil } repo.Status.LatestCommit.Hash = hash.String() return nil } // add files from another repository at specified path to target repository (gitea for now) func reconcileRemoteRepoContent(ctx context.Context, repo *v1alpha1.GitRepository, tgtRepo repoInfo, creds gitProviderCredentials, tmpDir string, repoMap *util.RepoMap) error { logger := log.FromContext(ctx) srcRepo := repo.Spec.Source.RemoteRepository cloneDir := util.RepoDir(srcRepo.Url, tmpDir) st := repoMap.LoadOrStore(srcRepo.Url, cloneDir) st.MU.Lock() defer st.MU.Unlock() logger.V(1).Info("cloning repo", "repoUrl", srcRepo.Url, "fallbackUrl", "", "cloneDir", cloneDir) remoteWT, _, err := util.CloneRemoteRepoToDir(ctx, srcRepo, 1, false, cloneDir, "") if err != nil { return fmt.Errorf("cloning repo, %s: %w", srcRepo.Url, err) } tgtRepoSpec := v1alpha1.RemoteRepositorySpec{ CloneSubmodules: false, Path: ".", Url: tgtRepo.cloneUrl, Ref: "", } tgtCloneDir := util.RepoDir(tgtRepo.cloneUrl, tmpDir) lst := repoMap.LoadOrStore(tgtRepoSpec.Url, tgtCloneDir) lst.MU.Lock() defer lst.MU.Unlock() logger.V(1).Info("cloning repo", "repoUrl", tgtRepoSpec.Url, "fallbackUrl", getFallbackRepositoryURL(repo, tgtRepo), "cloneDir", tgtCloneDir) tgtRepoWT, tgtRepository, err := util.CloneRemoteRepoToDir(ctx, tgtRepoSpec, 1, true, tgtCloneDir, getFallbackRepositoryURL(repo, tgtRepo)) if err != nil { return fmt.Errorf("cloning repo %s: %w", srcRepo.Url, err) } err = util.CopyTreeToTree(remoteWT, tgtRepoWT, fmt.Sprintf("/%s", repo.Spec.Source.Path), ".") if err != nil { return fmt.Errorf("copying contents, %s: %w", tgtRepo.cloneUrl, err) } hash, push, err := addAllAndCommit(repo.Spec.Source.Path, tgtRepository) if err != nil { return fmt.Errorf("add and commit %w", err) } if push { remoteUrl, err := util.FirstRemoteURL(tgtRepository) if err != nil { return fmt.Errorf("getting remote url %w", err) } logger.V(1).Info("pushing to remote url", "remoteUrl", remoteUrl) err = pushToRemote(ctx, tgtRepository, creds) if err != nil { return fmt.Errorf("pushing to git: %w", err) } repo.Status.LatestCommit.Hash = hash.String() return nil } repo.Status.LatestCommit.Hash = hash.String() return nil } func configureGitClient() { tr := http.DefaultTransport.(*http.Transport).Clone() tr.DialContext = (&net.Dialer{ Timeout: gitTCPTimeout, KeepAlive: 30 * time.Second, // from http.DefaultTransport }).DialContext customClient := &http.Client{ Transport: tr, Timeout: gitHTTPTimeout, } gitclient.InstallProtocol("https", githttp.NewClient(customClient)) gitclient.InstallProtocol("http", githttp.NewClient(customClient)) } ================================================ FILE: pkg/controllers/gitrepository/controller_test.go ================================================ package gitrepository import ( "context" "errors" "fmt" "os" "path/filepath" "testing" "time" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "code.gitea.io/sdk/gitea" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/object" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) const addFileContent = "added\n" type mockGitea struct { GiteaClient getRepo func() (*gitea.Repository, *gitea.Response, error) createRepo func() (*gitea.Repository, *gitea.Response, error) } func (g mockGitea) SetBasicAuth(user, pass string) {} func (g mockGitea) SetContext(ctx context.Context) {} func (g mockGitea) CreateOrgRepo(org string, opt gitea.CreateRepoOption) (*gitea.Repository, *gitea.Response, error) { if g.createRepo != nil { return g.createRepo() } return &gitea.Repository{}, &gitea.Response{}, nil } func (g mockGitea) GetRepo(owner, reponame string) (*gitea.Repository, *gitea.Response, error) { if g.getRepo != nil { return g.getRepo() } return &gitea.Repository{}, &gitea.Response{}, nil } type expect struct { resource v1alpha1.GitRepositoryStatus err error } type testCase struct { giteaClient GiteaClient input v1alpha1.GitRepository expect expect } func (t testCase) giteaProvider(ctx context.Context, repo *v1alpha1.GitRepository, kubeClient client.Client, scheme *runtime.Scheme, tmplConfig v1alpha1.BuildCustomizationSpec) (gitProvider, error) { return &giteaProvider{ Client: kubeClient, Scheme: scheme, giteaClient: t.giteaClient, config: tmplConfig, }, nil } type fakeClient struct { client.Client patchObj client.Object } func (f *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { s := obj.(*v1.Secret) s.Data = map[string][]byte{ giteaAdminUsernameKey: []byte("abc"), giteaAdminPasswordKey: []byte("abc"), corev1.TLSCertKey: []byte("abc"), corev1.TLSPrivateKeyKey: []byte("abc"), } return nil } func (f *fakeClient) Status() client.StatusWriter { return fakeStatusWriter{} } func (f *fakeClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { f.patchObj = obj return nil } type fakeStatusWriter struct { client.StatusWriter } func (f fakeStatusWriter) Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { return nil } func setUpLocalRepo() (string, string, error) { repoDir, err := os.MkdirTemp("", fmt.Sprintf("test")) if err != nil { return "", "", fmt.Errorf("creating temporary directory: %w", err) } // create a repo for pushing. MUST BE BARE repo, err := git.PlainInit(repoDir, true) if err != nil { return "", "", fmt.Errorf("repo init: %w", err) } // init it with a static file (in-memory), set default branch name, then get the hash defaultBranchName := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", DefaultBranchName)) repoConfig, _ := repo.Config() repoConfig.Init.DefaultBranch = DefaultBranchName repo.SetConfig(repoConfig) h := plumbing.NewSymbolicReference(plumbing.HEAD, defaultBranchName) repo.Storer.SetReference(h) fileObject := plumbing.MemoryObject{} fileObject.SetType(plumbing.BlobObject) w, _ := fileObject.Writer() file, err := os.ReadFile("test/resources/file1") if err != nil { return "", "", fmt.Errorf("reading file from resources dir: %w", err) } w.Write(file) w.Close() fileHash, _ := repo.Storer.SetEncodedObject(&fileObject) treeEntry := object.TreeEntry{ Name: "file1", Mode: filemode.Regular, Hash: fileHash, } tree := object.Tree{ Entries: []object.TreeEntry{treeEntry}, } treeObject := plumbing.MemoryObject{} tree.Encode(&treeObject) initHash, _ := repo.Storer.SetEncodedObject(&treeObject) commit := object.Commit{ Author: object.Signature{ Name: gitCommitAuthorName, Email: gitCommitAuthorEmail, When: time.Now(), }, Message: "init", TreeHash: initHash, } commitObject := plumbing.MemoryObject{} commit.Encode(&commitObject) commitHash, _ := repo.Storer.SetEncodedObject(&commitObject) repo.Storer.SetReference(plumbing.NewHashReference(defaultBranchName, commitHash)) return repoDir, commitHash.String(), nil } func setupDir() (string, error) { tempDir, err := os.MkdirTemp("", fmt.Sprintf("test")) if err != nil { return "", fmt.Errorf("creating temporary directory: %w", err) } file, err := os.ReadFile("test/resources/file1") if err != nil { return "", fmt.Errorf("reading file from resources dir: %w", err) } err = os.WriteFile(filepath.Join(tempDir, "file1"), file, 0644) if err != nil { return "", fmt.Errorf("writing file to temp dir: %w", err) } err = os.WriteFile(filepath.Join(tempDir, "add"), []byte(addFileContent), 0644) if err != nil { return "", fmt.Errorf("writing file: %w", err) } return tempDir, nil } func TestGitRepositoryContentReconcile(t *testing.T) { ctx := context.Background() localRepoDir, _, err := setUpLocalRepo() defer os.RemoveAll(localRepoDir) if err != nil { t.Fatalf("failed setting up local git repo: %v", err) } srcDir, err := setupDir() defer os.RemoveAll(srcDir) if err != nil { t.Fatalf("failed to set up dirs: %v", err) } testCloneDir, _ := os.MkdirTemp("", "gitrepo-test") defer os.RemoveAll(testCloneDir) m := metav1.ObjectMeta{ Name: "test", Namespace: "test", } resource := v1alpha1.GitRepository{ ObjectMeta: m, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Path: srcDir, Type: "local", }, }, } t.Run("files modified", func(t *testing.T) { p := giteaProvider{ Client: &fakeClient{}, giteaClient: mockGitea{}, } // add file to source directory, reconcile, clone the repo and check if the added file exists err = p.updateRepoContent(ctx, &resource, repoInfo{cloneUrl: localRepoDir}, gitProviderCredentials{}, testCloneDir, util.NewRepoLock()) if err != nil { t.Fatalf("failed adding %v", err) } repo, _ := git.PlainClone(testCloneDir, false, &git.CloneOptions{ URL: localRepoDir, }) c, err := os.ReadFile(filepath.Join(testCloneDir, "add")) if err != nil { t.Fatalf("failed to read file at %s. %v", filepath.Join(testCloneDir, "add"), err) } if string(c) != addFileContent { t.Fatalf("expected %s, got %s", addFileContent, c) } // remove added file, reconcile, pull, check if the file is removed err = os.Remove(filepath.Join(srcDir, "add")) if err != nil { t.Fatalf("failed to remove added file %v", err) } err = p.updateRepoContent(ctx, &resource, repoInfo{cloneUrl: localRepoDir}, gitProviderCredentials{}, testCloneDir, util.NewRepoLock()) if err != nil { t.Fatalf("failed removing %v", err) } w, _ := repo.Worktree() err = w.Pull(&git.PullOptions{}) if err != nil { t.Fatalf("failed pulling changes %v", err) } _, err = os.Stat(filepath.Join(testCloneDir, "add")) if err == nil { t.Fatalf("file should not exist") } if !errors.Is(err, os.ErrNotExist) { t.Fatalf("received unexpected error %v", err) } }) } func TestGitRepositoryContentReconcileEmbedded(t *testing.T) { ctx := context.Background() localRepoDir, _, err := setUpLocalRepo() defer os.RemoveAll(localRepoDir) if err != nil { t.Fatalf("failed setting up local git repo: %v", err) } tmpDir, _ := os.MkdirTemp("", "add") defer os.RemoveAll(tmpDir) m := metav1.ObjectMeta{ Name: "test", Namespace: "test", } resource := v1alpha1.GitRepository{ ObjectMeta: m, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ EmbeddedAppName: "nginx", Type: "embedded", }, Provider: v1alpha1.Provider{ InternalGitURL: "http://cnoe.io", }, }, } t.Run("should update content", func(t *testing.T) { p := giteaProvider{ Client: &fakeClient{}, giteaClient: mockGitea{}, } err = p.updateRepoContent(ctx, &resource, repoInfo{cloneUrl: localRepoDir}, gitProviderCredentials{}, tmpDir, util.NewRepoLock()) if err != nil { t.Fatalf("failed adding %v", err) } }) } func TestGitRepositoryReconcile(t *testing.T) { localReoDir, hash, err := setUpLocalRepo() defer os.RemoveAll(localReoDir) if err != nil { t.Fatalf("failed setting up local git repo: %v", err) } resourcePath, err := filepath.Abs("./test/resources") if err != nil { t.Fatalf("failed to get absolute path: %v", err) } updateDir, _, _ := setUpLocalRepo() defer os.RemoveAll(updateDir) addDir, err := setupDir() fmt.Println(addDir) defer os.RemoveAll(addDir) if err != nil { t.Fatalf("failed to set up dirs: %v", err) } tmpDir, _ := os.MkdirTemp("", "gitrepo-test") defer os.RemoveAll(tmpDir) m := metav1.ObjectMeta{ Name: "test", Namespace: "test", } cases := map[string]testCase{ "no op": { giteaClient: mockGitea{ getRepo: func() (*gitea.Repository, *gitea.Response, error) { return &gitea.Repository{CloneURL: localReoDir}, nil, nil }, }, input: v1alpha1.GitRepository{ ObjectMeta: m, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Path: resourcePath, Type: "local", }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, InternalGitURL: "http://cnoe.io", }, }, }, expect: expect{ resource: v1alpha1.GitRepositoryStatus{ ExternalGitRepositoryUrl: localReoDir, LatestCommit: v1alpha1.Commit{Hash: hash}, Synced: true, InternalGitRepositoryUrl: "http://cnoe.io/giteaAdmin/test-test.git", }, }, }, "update": { giteaClient: mockGitea{ getRepo: func() (*gitea.Repository, *gitea.Response, error) { return &gitea.Repository{CloneURL: updateDir}, nil, nil }, }, input: v1alpha1.GitRepository{ ObjectMeta: m, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Path: addDir, Type: "local", }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, InternalGitURL: "http://cnoe.io", }, }, }, expect: expect{ resource: v1alpha1.GitRepositoryStatus{ ExternalGitRepositoryUrl: updateDir, Synced: true, InternalGitRepositoryUrl: "http://cnoe.io/giteaAdmin/test-test.git", }, }, }, } ctx := context.Background() t.Run("repo updates", func(t *testing.T) { for k := range cases { v := cases[k] r := RepositoryReconciler{ Client: &fakeClient{}, GitProviderFunc: v.giteaProvider, TempDir: tmpDir, RepoMap: util.NewRepoLock(), } _, err := r.reconcileGitRepo(ctx, &v.input) if v.expect.err == nil && err != nil { t.Fatalf("failed %s: %v", k, err) } if v.expect.resource.LatestCommit.Hash == "" { v.expect.resource.LatestCommit.Hash = v.input.Status.LatestCommit.Hash } assert.Equal(t, v.input.Status, v.expect.resource) } }) } func TestGitRepositoryPostReconcile(t *testing.T) { c := fakeClient{} tmpDir, _ := os.MkdirTemp("", "repo-updates-test") defer os.RemoveAll(tmpDir) reconciler := RepositoryReconciler{ Client: &c, TempDir: tmpDir, RepoMap: util.NewRepoLock(), } testTime := time.Now().Format(time.RFC3339Nano) repo := v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "test", Annotations: map[string]string{ v1alpha1.CliStartTimeAnnotation: testTime, }, }, } reconciler.postProcessReconcile(context.Background(), ctrl.Request{}, &repo) annotations := c.patchObj.GetAnnotations() v, ok := annotations[v1alpha1.LastObservedCLIStartTimeAnnotation] if !ok { t.Fatalf("expected annotation not found: %s", v1alpha1.LastObservedCLIStartTimeAnnotation) } if v != testTime { t.Fatalf("annotation values does not match") } repo.Annotations[v1alpha1.LastObservedCLIStartTimeAnnotation] = "abc" reconciler.postProcessReconcile(context.Background(), ctrl.Request{}, &repo) v = annotations[v1alpha1.LastObservedCLIStartTimeAnnotation] if v != testTime { t.Fatalf("annotation values does not match") } } ================================================ FILE: pkg/controllers/gitrepository/git_repository.go ================================================ package gitrepository import ( "context" "code.gitea.io/sdk/gitea" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/google/go-github/v61/github" ) type GiteaClient interface { CreateAccessToken(option gitea.CreateAccessTokenOption) (*gitea.AccessToken, *gitea.Response, error) CreateOrg(opt gitea.CreateOrgOption) (*gitea.Organization, *gitea.Response, error) CreateRepo(opt gitea.CreateRepoOption) (*gitea.Repository, *gitea.Response, error) DeleteOrg(orgname string) (*gitea.Response, error) DeleteRepo(owner, repo string) (*gitea.Response, error) GetOrg(orgname string) (*gitea.Organization, *gitea.Response, error) GetRepo(owner, reponame string) (*gitea.Repository, *gitea.Response, error) SetBasicAuth(username, password string) SetContext(ctx context.Context) } type gitHubClient interface { getRepo(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error) createRepo(ctx context.Context, owner string, req *github.Repository) (*github.Repository, *github.Response, error) setToken(token string) error } type repoInfo struct { name string cloneUrl string internalGitRepositoryUrl string fullName string } type gitProviderCredentials struct { username string password string accessToken string } type gitProvider interface { createRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) getProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository) (gitProviderCredentials, error) getRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) setProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository, creds gitProviderCredentials) error updateRepoContent(ctx context.Context, repo *v1alpha1.GitRepository, repoInfo repoInfo, creds gitProviderCredentials, tmpDir string, repoMap *util.RepoMap) error } ================================================ FILE: pkg/controllers/gitrepository/gitea.go ================================================ package gitrepository import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/pkg/util/files" "os" "path/filepath" "code.gitea.io/sdk/gitea" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/controllers/localbuild" "github.com/cnoe-io/idpbuilder/pkg/util" githttp "github.com/go-git/go-git/v5/plumbing/transport/http" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( giteaAdminUsernameKey = "username" giteaAdminPasswordKey = "password" ) type GiteaClientFunc func(url string, options ...gitea.ClientOption) (GiteaClient, error) type giteaProvider struct { client.Client Scheme *runtime.Scheme giteaClient GiteaClient config v1alpha1.BuildCustomizationSpec } func (g *giteaProvider) createRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) { resp, _, err := g.giteaClient.CreateRepo(gitea.CreateRepoOption{ Name: getRepositoryName(*repo), Description: fmt.Sprintf("created by Git Repository controller for %s in %s namespace", repo.Name, repo.Namespace), // we should reconsider this when targeting non-local clusters. Private: false, DefaultBranch: DefaultBranchName, AutoInit: true, }) if err != nil { return repoInfo{}, fmt.Errorf("failed to create git repository: %w", err) } return repoInfo{ name: resp.Name, fullName: resp.FullName, cloneUrl: resp.CloneURL, }, nil } func (g *giteaProvider) getProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository) (gitProviderCredentials, error) { var secret v1.Secret err := g.Client.Get(ctx, types.NamespacedName{ Namespace: repo.Spec.SecretRef.Namespace, Name: repo.Spec.SecretRef.Name, }, &secret) if err != nil { return gitProviderCredentials{}, err } username, ok := secret.Data[giteaAdminUsernameKey] if !ok { return gitProviderCredentials{}, fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminUsernameKey, repo.Spec.SecretRef.Name, repo.Spec.SecretRef.Namespace) } password, ok := secret.Data[giteaAdminPasswordKey] if !ok { return gitProviderCredentials{}, fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminPasswordKey, repo.Spec.SecretRef.Name, repo.Spec.SecretRef.Namespace) } return gitProviderCredentials{ username: string(username), password: string(password), }, nil } func (g *giteaProvider) setProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository, creds gitProviderCredentials) error { g.giteaClient.SetBasicAuth(creds.username, creds.password) g.giteaClient.SetContext(ctx) return nil } func (g *giteaProvider) getRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) { resp, repoResp, err := g.giteaClient.GetRepo(getOrganizationName(*repo), getRepositoryName(*repo)) if err != nil { if repoResp != nil && repoResp.StatusCode == 404 { return repoInfo{}, notFoundError{} } return repoInfo{}, err } return repoInfo{ name: resp.Name, fullName: resp.FullName, cloneUrl: resp.CloneURL, internalGitRepositoryUrl: getInternalGiteaRepositoryURL(repo.Namespace, repo.Name, repo.Spec.Provider.InternalGitURL), }, nil } func (g *giteaProvider) updateRepoContent( ctx context.Context, repo *v1alpha1.GitRepository, repoInfo repoInfo, creds gitProviderCredentials, tmpDir string, repoMap *util.RepoMap, ) error { switch repo.Spec.Source.Type { case v1alpha1.SourceTypeLocal, v1alpha1.SourceTypeEmbedded: return reconcileLocalRepoContent(ctx, repo, repoInfo, creds, g.Scheme, g.config, tmpDir, repoMap) case v1alpha1.SourceTypeRemote: return reconcileRemoteRepoContent(ctx, repo, repoInfo, creds, tmpDir, repoMap) default: return nil } } func writeRepoContents(repo *v1alpha1.GitRepository, dstPath string, config v1alpha1.BuildCustomizationSpec, scheme *runtime.Scheme) error { if repo.Spec.Source.EmbeddedAppName != "" { resources, err := localbuild.GetEmbeddedRawInstallResources( repo.Spec.Source.EmbeddedAppName, config, v1alpha1.PackageCustomization{Name: repo.Spec.Customization.Name, FilePath: repo.Spec.Customization.FilePath}, scheme) if err != nil { return fmt.Errorf("getting embedded resource; %w", err) } for i := range resources { filePath := filepath.Join(dstPath, fmt.Sprintf("resource%d.yaml", i)) err = os.WriteFile(filePath, resources[i], 0644) if err != nil { return fmt.Errorf("writing embedded resource; %w", err) } } return nil } err := files.CopyDirectory(repo.Spec.Source.Path, dstPath) if err != nil { return fmt.Errorf("copying files: %w", err) } return nil } func getBasicAuth(creds gitProviderCredentials) (githttp.BasicAuth, error) { b := githttp.BasicAuth{ Username: creds.username, Password: creds.password, } if creds.password == "" { b.Password = creds.accessToken } return b, nil } func NewGiteaClient(url string, options ...gitea.ClientOption) (GiteaClient, error) { return gitea.NewClient(url, options...) } func getInternalGiteaRepositoryURL(namespace, name, baseUrl string) string { return fmt.Sprintf("%s/%s/%s-%s.git", baseUrl, v1alpha1.GiteaAdminUserName, namespace, name) } ================================================ FILE: pkg/controllers/gitrepository/github.go ================================================ package gitrepository import ( "context" "fmt" "net/http" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/google/go-github/v61/github" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( gitHubTokenKey = "token" ) type ghClient struct { c *github.Client } func (g *ghClient) getRepo(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error) { return g.c.Repositories.Get(ctx, owner, repo) } func (g *ghClient) createRepo(ctx context.Context, owner string, req *github.Repository) (*github.Repository, *github.Response, error) { return g.c.Repositories.Create(ctx, owner, req) } func (g *ghClient) setToken(token string) error { g.c = g.c.WithAuthToken(token) return nil } type gitHubProvider struct { client.Client Scheme *runtime.Scheme gitHubClient gitHubClient config v1alpha1.BuildCustomizationSpec } func (g *gitHubProvider) createRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) { req := github.Repository{ Name: github.String(getRepositoryName(*repo)), Private: github.Bool(true), } r, _, err := g.gitHubClient.createRepo(ctx, getOrganizationName(*repo), &req) if err != nil { return repoInfo{}, fmt.Errorf("creating repo: %w", err) } return repoInfo{ name: *r.Name, cloneUrl: *r.CloneURL, internalGitRepositoryUrl: "", fullName: *r.FullName, }, nil } func (g *gitHubProvider) getRepository(ctx context.Context, repo *v1alpha1.GitRepository) (repoInfo, error) { r, resp, err := g.gitHubClient.getRepo(ctx, getOrganizationName(*repo), getRepositoryName(*repo)) if err != nil { if resp != nil && resp.StatusCode == http.StatusNotFound { return repoInfo{}, notFoundError{} } else { return repoInfo{}, fmt.Errorf("getting repo: %w", err) } } return repoInfo{ name: *r.Name, cloneUrl: *r.CloneURL, internalGitRepositoryUrl: "", fullName: *r.FullName, }, nil } func (g *gitHubProvider) getProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository) (gitProviderCredentials, error) { var secret v1.Secret err := g.Client.Get(ctx, types.NamespacedName{ Namespace: repo.Spec.SecretRef.Namespace, Name: repo.Spec.SecretRef.Name, }, &secret) if err != nil { return gitProviderCredentials{}, err } token, ok := secret.Data[gitHubTokenKey] if !ok { return gitProviderCredentials{}, fmt.Errorf("%s key not found in secret %s in %s ns", giteaAdminUsernameKey, repo.Spec.SecretRef.Name, repo.Spec.SecretRef.Namespace) } return gitProviderCredentials{ accessToken: string(token), }, nil } func (g *gitHubProvider) setProviderCredentials(ctx context.Context, repo *v1alpha1.GitRepository, creds gitProviderCredentials) error { return g.gitHubClient.setToken(creds.accessToken) } func (g *gitHubProvider) updateRepoContent( ctx context.Context, repo *v1alpha1.GitRepository, repoInfo repoInfo, creds gitProviderCredentials, tmpDir string, repoMap *util.RepoMap, ) error { return reconcileLocalRepoContent(ctx, repo, repoInfo, creds, g.Scheme, g.config, tmpDir, repoMap) } func newGitHubClient(httpClient *http.Client) gitHubClient { return &ghClient{ c: github.NewClient(httpClient), } } ================================================ FILE: pkg/controllers/gitrepository/github_test.go ================================================ package gitrepository import ( "context" "fmt" "net/http" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/google/go-github/v61/github" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) type fakeGH struct { mock.Mock } func (f *fakeGH) getRepo(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error) { args := f.Called(ctx, owner, repo) return args.Get(0).(*github.Repository), args.Get(1).(*github.Response), args.Error(2) } func (f *fakeGH) createRepo(ctx context.Context, owner string, req *github.Repository) (*github.Repository, *github.Response, error) { args := f.Called(ctx, owner, req) return args.Get(0).(*github.Repository), args.Get(1).(*github.Response), args.Error(2) } func (f *fakeGH) setToken(token string) error { return nil } func newResponse(r http.Response) *github.Response { response := &github.Response{Response: &r} return response } type fakeKubeClient struct { mock.Mock client.Client } func (f *fakeKubeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { args := f.Called(ctx, key, obj, opts) return args.Error(0) } func TestGitHubCreateRepository(t *testing.T) { fakeGH := new(fakeGH) ctx := context.Background() gh := gitHubProvider{ Client: &fakeClient{}, gitHubClient: fakeGH, } repoExpected := repoInfo{ name: "repo1", cloneUrl: "", internalGitRepositoryUrl: "", fullName: "owner/test-test", } resource := v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Path: "ac", Type: "local", }, Provider: v1alpha1.Provider{ Name: "github", OrganizationName: "owner", }, }, } expectedInput := &github.Repository{ Name: github.String(getRepositoryName(resource)), Private: github.Bool(true), } fakeGH.On("createRepo", ctx, "owner", expectedInput).Return( &github.Repository{ Name: &repoExpected.name, CloneURL: &repoExpected.cloneUrl, FullName: &repoExpected.fullName, }, newResponse(http.Response{StatusCode: http.StatusOK}), nil, ) resp, err := gh.createRepository(ctx, &resource) assert.Nil(t, err) assert.Equal(t, repoExpected, resp) fakeGH.AssertExpectations(t) } func TestGitHubGetProviderCredentials(t *testing.T) { fakeK8sClient := new(fakeKubeClient) ctx := context.Background() gh := gitHubProvider{ Client: fakeK8sClient, } resource := v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ SecretRef: v1alpha1.SecretReference{ Name: "test", Namespace: "testNS", }, }, } inputSecret := &v1.Secret{} fakeK8sClient.On("Get", ctx, types.NamespacedName{ Namespace: "testNS", Name: "test", }, inputSecret, []client.GetOption(nil)).Run(func(args mock.Arguments) { sec := args.Get(2).(*v1.Secret) sec.Data = make(map[string][]byte, 1) sec.Data[gitHubTokenKey] = []byte("token") }).Return(nil) creds, err := gh.getProviderCredentials(ctx, &resource) assert.Nil(t, err) assert.Equal(t, creds.accessToken, "token") fakeK8sClient.AssertExpectations(t) } func TestGitHubGetRepository(t *testing.T) { fakeGH := new(fakeGH) ctx := context.Background() gh := gitHubProvider{ Client: &fakeClient{}, gitHubClient: fakeGH, } repoExpected := repoInfo{ name: "repo1", cloneUrl: "", internalGitRepositoryUrl: "", fullName: "owner/test-test", } fakeGetRepo := fakeGH.On("getRepo", ctx, "owner", "test-test").Return( &github.Repository{ Name: &repoExpected.name, CloneURL: &repoExpected.cloneUrl, FullName: &repoExpected.fullName, }, newResponse(http.Response{StatusCode: http.StatusOK}), nil, ) resource := v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "test", }, Spec: v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Path: "ac", Type: "local", }, Provider: v1alpha1.Provider{ Name: "github", OrganizationName: "owner", }, }, } resp, err := gh.getRepository(ctx, &resource) assert.Nil(t, err) assert.Equal(t, repoExpected, resp) fakeGH.AssertExpectations(t) fakeGetRepo.Unset() fakeGH.On("getRepo", ctx, "owner", "test-test").Return( &github.Repository{}, newResponse(http.Response{StatusCode: http.StatusNotFound}), fmt.Errorf("some error"), ) resp, err = gh.getRepository(ctx, &resource) assert.Equal(t, notFoundError{}, err) assert.Equal(t, repoInfo{}, resp) fakeGH.AssertExpectations(t) } ================================================ FILE: pkg/controllers/gitrepository/test/resources/file1 ================================================ hello ================================================ FILE: pkg/controllers/localbuild/argo.go ================================================ package localbuild import ( "context" "embed" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" ) //go:embed resources/argo/* var installArgoFS embed.FS func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { return k8s.BuildCustomizedManifests(config.FilePath, "resources/argo", installArgoFS, scheme, templateData) } func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { argocd := EmbeddedInstallation{ name: "Argo CD", resourcePath: "resources/argo", resourceFS: installArgoFS, namespace: globals.ArgoCDNamespace, monitoredResources: map[string]schema.GroupVersionKind{ "argocd-server": { Group: "apps", Version: "v1", Kind: "Deployment", }, "argocd-repo-server": { Group: "apps", Version: "v1", Kind: "Deployment", }, "argocd-application-controller": { Group: "apps", Version: "v1", Kind: "StatefulSet", }, }, skipReadinessCheck: true, } v, ok := resource.Spec.PackageConfigs.CorePackageCustomization[v1alpha1.ArgoCDPackageName] if ok { argocd.customization = v } if result, err := argocd.Install(ctx, resource, r.Client, r.Scheme, r.Config); err != nil { return result, err } resource.Status.ArgoCD.Available = true return ctrl.Result{}, nil } ================================================ FILE: pkg/controllers/localbuild/argo_test.go ================================================ package localbuild import ( "context" "github.com/cnoe-io/idpbuilder/pkg/util/fs" "testing" argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" ) type fakeKubeClient struct { mock.Mock client.Client } func (f *fakeKubeClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { args := f.Called(ctx, list, opts) return args.Error(0) } func (f *fakeKubeClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { args := f.Called(ctx, obj, patch, opts) return args.Error(0) } type testCase struct { err error listApps []argov1alpha1.Application annotations []map[string]string } func TestGetRawInstallResources(t *testing.T) { e := EmbeddedInstallation{ resourceFS: installArgoFS, resourcePath: "resources/argo", } resources, err := fs.ConvertFSToBytes(e.resourceFS, e.resourcePath, v1alpha1.BuildCustomizationSpec{ Protocol: "", Host: "", Port: "", UsePathRouting: false, }, ) if err != nil { t.Fatalf("GetRawInstallResources() error: %v", err) } if len(resources) != 2 { t.Fatalf("GetRawInstallResources() resources len != 2, got %d", len(resources)) } resourcePrefix := "# UCP ARGO INSTALL RESOURCES\n" checkPrefix := resources[1][0:len(resourcePrefix)] if resourcePrefix != string(checkPrefix) { t.Fatalf("GetRawInstallResources() expected 1 resource with prefix %q, got %q", resourcePrefix, checkPrefix) } } func TestGetK8sInstallResources(t *testing.T) { e := EmbeddedInstallation{ resourceFS: installArgoFS, resourcePath: "resources/argo", } objs, err := e.installResources(k8s.GetScheme(), v1alpha1.BuildCustomizationSpec{ Protocol: "", Host: "", Port: "", UsePathRouting: false, }) if err != nil { t.Fatalf("GetK8sInstallResources() error: %v", err) } if len(objs) != 60 { t.Fatalf("Expected 60 Argo Install Resources, got: %d", len(objs)) } } func TestArgoCDAppAnnotation(t *testing.T) { ctx := context.Background() cases := []testCase{ { err: nil, listApps: []argov1alpha1.Application{ { TypeMeta: metav1.TypeMeta{ Kind: argov1alpha1.ApplicationSchemaGroupVersionKind.Kind, APIVersion: argov1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "nil-annotation", Namespace: "argocd", }, }, }, annotations: []map[string]string{ { argoCDApplicationAnnotationKeyRefresh: argoCDApplicationAnnotationValueRefreshNormal, }, }, }, { err: nil, listApps: []argov1alpha1.Application{ { TypeMeta: metav1.TypeMeta{ Kind: argov1alpha1.ApplicationSchemaGroupVersionKind.Kind, APIVersion: argov1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "existing-annotation", Namespace: "argocd", Annotations: map[string]string{ "test": "value", }, }, }, }, annotations: []map[string]string{ { "test": "value", argoCDApplicationAnnotationKeyRefresh: argoCDApplicationAnnotationValueRefreshNormal, }, }, }, { err: nil, listApps: []argov1alpha1.Application{ { TypeMeta: metav1.TypeMeta{ Kind: argov1alpha1.ApplicationSchemaGroupVersionKind.Kind, APIVersion: argov1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "owned-by-appset", Namespace: "argocd", Annotations: map[string]string{ "test": "value", }, OwnerReferences: []metav1.OwnerReference{ { Kind: "ApplicationSet", }, }, }, }, }, annotations: nil, }, { err: nil, listApps: []argov1alpha1.Application{ { TypeMeta: metav1.TypeMeta{ Kind: argov1alpha1.ApplicationSchemaGroupVersionKind.Kind, APIVersion: argov1alpha1.ApplicationSchemaGroupVersionKind.GroupVersion().String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "owned-by-non-appset", Namespace: "argocd", OwnerReferences: []metav1.OwnerReference{ { Kind: "Something", }, }, }, }, }, annotations: []map[string]string{ { argoCDApplicationAnnotationKeyRefresh: argoCDApplicationAnnotationValueRefreshNormal, }, }, }, } for i := range cases { c := cases[i] fClient := new(fakeKubeClient) fClient.On("List", ctx, mock.Anything, []client.ListOption{client.InNamespace(globals.ArgoCDNamespace)}). Run(func(args mock.Arguments) { apps := args.Get(1).(*argov1alpha1.ApplicationList) apps.Items = c.listApps }).Return(c.err) for j := range c.annotations { app := c.listApps[j] u := makeUnstructured(app.Name, app.Namespace, app.GroupVersionKind(), c.annotations[j]) fClient.On("Patch", ctx, u, client.Apply, []client.PatchOption{client.FieldOwner(v1alpha1.FieldManager)}).Return(nil) } rec := LocalbuildReconciler{ Client: fClient, } err := rec.requestArgoCDAppRefresh(ctx) fClient.AssertExpectations(t) assert.NoError(t, err) } } func makeUnstructured(name, namespace string, gvk schema.GroupVersionKind, annotations map[string]string) *unstructured.Unstructured { u := &unstructured.Unstructured{} u.SetAnnotations(annotations) u.SetName(name) u.SetNamespace(namespace) u.SetGroupVersionKind(gvk) return u } ================================================ FILE: pkg/controllers/localbuild/controller.go ================================================ package localbuild import ( "bytes" "code.gitea.io/sdk/gitea" "context" "encoding/json" "fmt" "io" "k8s.io/apimachinery/pkg/types" "net/http" "os" "path/filepath" "strings" "sync" "time" argocdapp "github.com/cnoe-io/argocd-api/api/argo/application" argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/resources/localbuild" "github.com/cnoe-io/idpbuilder/pkg/util" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/selection" "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" ) const ( defaultArgoCDProjectName string = "default" defaultRequeueTime = time.Second * 15 errRequeueTime = time.Second * 5 argoCDApplicationAnnotationKeyRefresh = "argocd.argoproj.io/refresh" argoCDApplicationAnnotationValueRefreshNormal = "normal" argoCDApplicationSetAnnotationKeyRefresh = "argocd.argoproj.io/application-set-refresh" argoCDApplicationSetAnnotationKeyRefreshTrue = "true" ) type ArgocdSession struct { Token string `json:"token"` } type LocalbuildReconciler struct { client.Client Scheme *runtime.Scheme CancelFunc context.CancelFunc ExitOnSync bool shouldShutdown bool Config v1alpha1.BuildCustomizationSpec TempDir string RepoMap *util.RepoMap } type subReconciler func(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) func (r *LocalbuildReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx) logger.V(1).Info("Reconciling", "resource", req.NamespacedName) var localBuild v1alpha1.Localbuild if err := r.Get(ctx, req.NamespacedName, &localBuild); err != nil { logger.Error(err, "unable to fetch Resource") // we'll ignore not-found errors, since they can't be fixed by an immediate // requeue (we'll need to wait for a new notification), and we can get them // on deleted requests. return ctrl.Result{}, client.IgnoreNotFound(err) } // Make sure we post process defer r.postProcessReconcile(ctx, req, &localBuild) _, err := r.ReconcileProjectNamespace(ctx, req, &localBuild) if err != nil { return ctrl.Result{}, err } instCtx, cancel := context.WithCancel(ctx) defer cancel() errChan := make(chan error, 3) go r.installCorePackages(instCtx, req, &localBuild, errChan) select { case <-ctx.Done(): return ctrl.Result{}, nil case instErr := <-errChan: if instErr != nil { // likely due to ingress-nginx admission hook not ready. debug log and try again. logger.V(1).Info("failed installing core package. likely not fatal. will try again", "error", instErr) return ctrl.Result{RequeueAfter: errRequeueTime}, nil } } if r.Config.StaticPassword { logger.V(1).Info("static password is enabled") // Check if the Argocd Initial admin secret exists argocdInitialAdminPassword, err := r.extractArgocdInitialAdminSecret(ctx) if err != nil { // Argocd initial admin secret is not yet available ... return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil } logger.V(1).Info("Initial argocd admin secret found ...") // Secret containing the initial argocd password exists // Lets try to update the password if argocdInitialAdminPassword != "" && argocdInitialAdminPassword != util.StaticPassword { err = r.updateArgocdPassword(ctx, argocdInitialAdminPassword) if err != nil { return ctrl.Result{}, err } else { logger.V(1).Info(fmt.Sprintf("Argocd admin password change succeeded !")) } } // Check if the Gitea credentials secret exists giteaAdminPassword, err := r.extractGiteaAdminSecret(ctx) if err != nil { // Gitea admin secret is not yet available ... return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil } logger.V(1).Info("Gitea admin secret found ...") // Secret containing the gitea password exists // Lets try to update the password if giteaAdminPassword != "" && giteaAdminPassword != util.StaticPassword { err = r.updateGiteaPassword(ctx, giteaAdminPassword) if err != nil { return ctrl.Result{}, err } else { logger.V(1).Info(fmt.Sprintf("Gitea admin password change succeeded !")) } } } logger.V(1).Info("done installing core packages. passing control to argocd") _, err = r.ReconcileArgoAppsWithGitea(ctx, req, &localBuild) if err != nil { return ctrl.Result{}, err } return ctrl.Result{RequeueAfter: defaultRequeueTime}, nil } func (r *LocalbuildReconciler) installCorePackages(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild, errChan chan error) { logger := log.FromContext(ctx) defer close(errChan) var wg sync.WaitGroup installers := map[string]subReconciler{ v1alpha1.IngressNginxPackageName: r.ReconcileNginx, v1alpha1.ArgoCDPackageName: r.ReconcileArgo, v1alpha1.GiteaPackageName: r.ReconcileGitea, } logger.V(1).Info("installing core packages") for k, v := range installers { wg.Add(1) name := k inst := v go func() { defer wg.Done() _, iErr := inst(ctx, req, resource) if iErr != nil { logger.V(1).Info("failed installing", "name", name, "error", iErr) errChan <- fmt.Errorf("failed installing %s: %w", name, iErr) } }() } wg.Wait() } // Responsible to updating ObservedGeneration in status func (r *LocalbuildReconciler) postProcessReconcile(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) { logger := log.FromContext(ctx) logger.Info("Checking if we should shutdown") if r.shouldShutdown { logger.Info("Shutting Down") err := r.requestArgoCDAppRefresh(ctx) if err != nil { logger.V(1).Info("failed requesting argocd application refresh", "error", err) } err = r.requestArgoCDAppSetRefresh(ctx) if err != nil { logger.V(1).Info("failed requesting argocd application set refresh", "error", err) } r.CancelFunc() return } resource.Status.ObservedGeneration = resource.GetGeneration() if err := r.Status().Update(ctx, resource); err != nil { logger.Error(err, "Failed to update resource status after reconcile") } } func (r *LocalbuildReconciler) ReconcileProjectNamespace(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { logger := log.FromContext(ctx) nsResource := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: globals.GetProjectNamespace(resource.Name), }, } logger.V(1).Info("Create or update namespace", "resource", nsResource) _, err := controllerutil.CreateOrUpdate(ctx, r.Client, nsResource, func() error { if err := controllerutil.SetControllerReference(resource, nsResource, r.Scheme); err != nil { logger.Error(err, "Setting controller ref on namespace resource") return err } return nil }) if err != nil { logger.Error(err, "Create or update namespace resource") } return ctrl.Result{}, err } // SetupWithManager sets up the controller with the Manager. func (r *LocalbuildReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.Localbuild{}). Complete(r) } func (r *LocalbuildReconciler) ReconcileArgoAppsWithGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { logger := log.FromContext(ctx) logger.Info("installing bootstrap apps to ArgoCD") // push bootstrap app manifests to Gitea. let ArgoCD take over // will need a way to filter them based on user input bootStrapApps := []string{v1alpha1.ArgoCDPackageName, v1alpha1.IngressNginxPackageName, v1alpha1.GiteaPackageName} for _, n := range bootStrapApps { result, err := r.reconcileEmbeddedApp(ctx, n, resource) if err != nil { return result, fmt.Errorf("reconciling bootstrap apps %w", err) } } // Process packages in REVERSE order (highest priority first) to avoid creating // lower priority packages first then having to delete them for i := len(resource.Spec.PackageConfigs.CustomPackageDirs) - 1; i >= 0; i-- { s := resource.Spec.PackageConfigs.CustomPackageDirs[i] result, err := r.reconcileCustomPkgDir(ctx, resource, s, i) if err != nil { return result, err } } for i := len(resource.Spec.PackageConfigs.CustomPackageFiles) - 1; i >= 0; i-- { s := resource.Spec.PackageConfigs.CustomPackageFiles[i] result, err := r.reconcileCustomPkgFile(ctx, resource, s, i) if err != nil { return result, err } } for i := len(resource.Spec.PackageConfigs.CustomPackageUrls) - 1; i >= 0; i-- { s := resource.Spec.PackageConfigs.CustomPackageUrls[i] result, err := r.reconcileCustomPkgUrl(ctx, resource, s, i) if err != nil { return result, err } } shutdown, err := r.shouldShutDown(ctx, resource) if err != nil { return ctrl.Result{Requeue: true}, err } r.shouldShutdown = shutdown return ctrl.Result{}, nil } func (r *LocalbuildReconciler) reconcileEmbeddedApp(ctx context.Context, appName string, resource *v1alpha1.Localbuild) (ctrl.Result, error) { logger := log.FromContext(ctx) logger.V(1).Info("Ensuring embedded ArgoCD Application", "name", appName) repo, err := r.reconcileGitRepo(ctx, resource, "embedded", appName, appName, "") if err != nil { return ctrl.Result{}, fmt.Errorf("creating %s repo CR: %w", appName, err) } app := &argov1alpha1.Application{ ObjectMeta: metav1.ObjectMeta{ Name: appName, Namespace: globals.ArgoCDNamespace, }, } util.SetPackageLabels(app) if err := controllerutil.SetControllerReference(resource, app, r.Scheme); err != nil { return ctrl.Result{}, err } err = r.Client.Get(ctx, client.ObjectKeyFromObject(app), app) if err != nil && k8serrors.IsNotFound(err) { localbuild.SetApplicationSpec( app, repo.Status.InternalGitRepositoryUrl, ".", defaultArgoCDProjectName, appName, nil, ) err = r.Client.Create(ctx, app) if err != nil { return ctrl.Result{}, fmt.Errorf("creating %s app CR: %w", appName, err) } } localbuild.SetApplicationSpec( app, repo.Status.InternalGitRepositoryUrl, ".", defaultArgoCDProjectName, appName, nil, ) err = r.Client.Update(ctx, app) if err != nil { return ctrl.Result{}, fmt.Errorf("updating argoapp: %w", err) } return ctrl.Result{}, nil } func (r *LocalbuildReconciler) shouldShutDown(ctx context.Context, resource *v1alpha1.Localbuild) (bool, error) { logger := log.FromContext(ctx) if !r.ExitOnSync { return false, nil } cliStartTime, err := util.GetCLIStartTimeAnnotationValue(resource.Annotations) if err != nil { return false, err } // check if core packages are ready selector := labels.NewSelector() req, err := labels.NewRequirement(v1alpha1.PackageTypeLabelKey, selection.Equals, []string{v1alpha1.PackageTypeLabelCore}) if err != nil { return false, fmt.Errorf("building labels with key %s and value %s : %w", v1alpha1.PackageTypeLabelKey, v1alpha1.PackageTypeLabelCore, err) } opts := client.ListOptions{ LabelSelector: selector.Add(*req), Namespace: "", } apps := argov1alpha1.ApplicationList{} err = r.Client.List(ctx, &apps, &opts) if err != nil { return false, fmt.Errorf("listing core packages: %w", err) } for _, app := range apps.Items { if app.Status.Health.Status != "Healthy" { return false, nil } } // check if repositories are ready repos := &v1alpha1.GitRepositoryList{} err = r.Client.List(ctx, repos, client.InNamespace(resource.Namespace)) if err != nil { return false, fmt.Errorf("listing repositories %w", err) } for i := range repos.Items { repo := repos.Items[i] startTimeAnnotation, gErr := util.GetCLIStartTimeAnnotationValue(repo.ObjectMeta.Annotations) if gErr != nil { // this means this repository resource is not managed by localbuild continue } // this object is not part of this CLI invocation if startTimeAnnotation != cliStartTime { continue } observedTime, gErr := util.GetLastObservedSyncTimeAnnotationValue(repo.ObjectMeta.Annotations) if gErr != nil { logger.Info(gErr.Error()) return false, nil } if !repo.Status.Synced || cliStartTime != observedTime { return false, nil } } // check if custom packages are ready pkgs := &v1alpha1.CustomPackageList{} err = r.Client.List(ctx, pkgs, client.InNamespace(resource.Namespace)) if err != nil { return false, fmt.Errorf("listing custom packages %w", err) } for i := range pkgs.Items { pkg := pkgs.Items[i] startTimeAnnotation, gErr := util.GetCLIStartTimeAnnotationValue(pkg.ObjectMeta.Annotations) if gErr != nil { continue } if startTimeAnnotation != cliStartTime { return false, nil } observedTime, gErr := util.GetLastObservedSyncTimeAnnotationValue(pkg.ObjectMeta.Annotations) if gErr != nil { logger.Info(gErr.Error()) return false, nil } if !pkg.Status.Synced || cliStartTime != observedTime { return false, nil } } return true, nil } func (r *LocalbuildReconciler) reconcileCustomPkg( ctx context.Context, resource *v1alpha1.Localbuild, b []byte, filePath string, remote *util.KustomizeRemote, priority int, sourcePath string, ) error { o := &unstructured.Unstructured{} _, gvk, fErr := scheme.Codecs.UniversalDeserializer().Decode(b, nil, o) if fErr != nil { return fErr } if isSupportedArgoCDTypes(gvk) { kind := o.GetKind() appName := o.GetName() appNS := o.GetNamespace() // Check if a higher-priority CustomPackage already exists for this app projectNS := globals.GetProjectNamespace(resource.Name) existingPkgs := &v1alpha1.CustomPackageList{} if err := r.Client.List(ctx, existingPkgs, client.InNamespace(projectNS)); err != nil { return fmt.Errorf("listing existing custom packages: %w", err) } for i := range existingPkgs.Items { existingPkg := &existingPkgs.Items[i] // Check if this package is for the same ArgoCD app if existingPkg.Spec.ArgoCD.Name == appName { // Get existing package's priority existingPriorityStr, exists := existingPkg.ObjectMeta.Annotations[v1alpha1.PackagePriorityAnnotation] if exists { var existingPriority int if _, err := fmt.Sscanf(existingPriorityStr, "%d", &existingPriority); err == nil { if existingPriority > priority { // A higher priority package already exists, skip this one existingSourcePath := existingPkg.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation] log.FromContext(ctx).Info("Skipping CustomPackage creation - higher priority package already exists", "appName", appName, "skippingPackage", sourcePath, "skippingPriority", priority, "keepingPackage", existingSourcePath, "keepingPriority", existingPriority) return nil } else if existingPriority < priority { // We have higher priority, delete the existing lower-priority package existingSourcePath := existingPkg.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation] log.FromContext(ctx).Info("Deleting lower priority CustomPackage", "appName", appName, "deletingPackage", existingSourcePath, "deletingPriority", existingPriority, "usingPackage", sourcePath, "usingPriority", priority) if err := r.Client.Delete(ctx, existingPkg); err != nil && !k8serrors.IsNotFound(err) { return fmt.Errorf("deleting lower priority package: %w", err) } } } } } } customPkg := &v1alpha1.CustomPackage{ ObjectMeta: metav1.ObjectMeta{ Name: getCustomPackageName(filepath.Base(filePath), appName), Namespace: projectNS, }, } cliStartTime, _ := util.GetCLIStartTimeAnnotationValue(resource.ObjectMeta.Annotations) _, fErr = controllerutil.CreateOrUpdate(ctx, r.Client, customPkg, func() error { if err := controllerutil.SetControllerReference(resource, customPkg, r.Scheme); err != nil { return err } if customPkg.ObjectMeta.Annotations == nil { customPkg.ObjectMeta.Annotations = make(map[string]string) } util.SetCLIStartTimeAnnotationValue(customPkg.ObjectMeta.Annotations, cliStartTime) customPkg.ObjectMeta.Annotations[v1alpha1.PackagePriorityAnnotation] = fmt.Sprintf("%d", priority) customPkg.ObjectMeta.Annotations[v1alpha1.PackageSourcePathAnnotation] = sourcePath customPkg.Spec = v1alpha1.CustomPackageSpec{ Replicate: true, GitServerURL: resource.Status.Gitea.ExternalURL, InternalGitServeURL: resource.Status.Gitea.InternalURL, GitServerAuthSecretRef: v1alpha1.SecretReference{ Name: resource.Status.Gitea.AdminUserSecretName, Namespace: resource.Status.Gitea.AdminUserSecretNamespace, }, ArgoCD: v1alpha1.ArgoCDPackageSpec{ ApplicationFile: filePath, Name: appName, Namespace: appNS, Type: kind, }, } if remote != nil { customPkg.Spec.RemoteRepository = v1alpha1.RemoteRepositorySpec{ Url: remote.CloneUrl(), Ref: remote.Ref, CloneSubmodules: remote.Submodules, Path: remote.Path(), } } return nil }) return fErr } return nil } func (r *LocalbuildReconciler) reconcileCustomPkgUrl(ctx context.Context, resource *v1alpha1.Localbuild, pkgUrl string, priority int) (ctrl.Result, error) { logger := log.FromContext(ctx) remote, err := util.NewKustomizeRemote(pkgUrl) if err != nil { return ctrl.Result{}, fmt.Errorf("parsing url, %s: %w", pkgUrl, err) } rs := v1alpha1.RemoteRepositorySpec{ Url: remote.CloneUrl(), Ref: remote.Ref, CloneSubmodules: remote.Submodules, Path: remote.Path(), } cloneDir := util.RepoDir(rs.Url, r.TempDir) st := r.RepoMap.LoadOrStore(rs.Url, cloneDir) st.MU.Lock() defer st.MU.Unlock() wt, _, err := util.CloneRemoteRepoToDir(ctx, rs, 1, false, cloneDir, "") if err != nil { return ctrl.Result{}, fmt.Errorf("cloning repo, %s: %w", pkgUrl, err) } yamlFiles, err := util.GetWorktreeYamlFiles(remote.Path(), wt, false) if err != nil { return ctrl.Result{}, fmt.Errorf("getting yaml files from repo, %s: %w", pkgUrl, err) } for _, yamlFile := range yamlFiles { b, fErr := util.ReadWorktreeFile(wt, yamlFile) if fErr != nil { logger.V(1).Info("processing", "file", yamlFile, "err", fErr) continue } rErr := r.reconcileCustomPkg(ctx, resource, b, yamlFile, remote, priority, pkgUrl) if rErr != nil { logger.Error(rErr, "reconciling custom pkg", "file", yamlFile, "pkgUrl", pkgUrl) } } return ctrl.Result{}, nil } func (r *LocalbuildReconciler) reconcileCustomPkgDir(ctx context.Context, resource *v1alpha1.Localbuild, pkgDir string, priority int) (ctrl.Result, error) { logger := log.FromContext(ctx) files, err := os.ReadDir(pkgDir) if err != nil { return ctrl.Result{}, fmt.Errorf("reading dir, %s: %w", pkgDir, err) } for i := range files { file := files[i] if !file.Type().IsRegular() || !util.IsYamlFile(file.Name()) { continue } filePath := filepath.Join(pkgDir, file.Name()) b, fErr := os.ReadFile(filePath) if fErr != nil { logger.Error(fErr, "reading file", "file", filePath) continue } rErr := r.reconcileCustomPkg(ctx, resource, b, filePath, nil, priority, pkgDir) if rErr != nil { logger.Error(rErr, "reconciling custom pkg", "file", filePath, "pkgDir", pkgDir) } } return ctrl.Result{}, nil } func (r *LocalbuildReconciler) reconcileCustomPkgFile(ctx context.Context, resource *v1alpha1.Localbuild, pkgFile string, priority int) (ctrl.Result, error) { logger := log.FromContext(ctx) file, err := os.Open(pkgFile) defer file.Close() if err != nil { return ctrl.Result{}, fmt.Errorf("opening file, %s: %w", pkgFile, err) } fType, err := file.Stat() if err != nil { return ctrl.Result{}, fmt.Errorf("getting file info, %s: %w", pkgFile, err) } if !fType.Mode().IsRegular() { return ctrl.Result{}, fmt.Errorf("file is not a regular file, %s: %w", pkgFile, err) } if !util.IsYamlFile(file.Name()) { return ctrl.Result{}, fmt.Errorf("file is not a yaml file, %s: %w", pkgFile, err) } b, fErr := os.ReadFile(pkgFile) if fErr != nil { return ctrl.Result{}, fmt.Errorf("reading file, %s: %w", pkgFile, err) } rErr := r.reconcileCustomPkg(ctx, resource, b, pkgFile, nil, priority, pkgFile) if rErr != nil { logger.Error(rErr, "reconciling custom pkg", "file", pkgFile) } return ctrl.Result{}, nil } func (r *LocalbuildReconciler) reconcileGitRepo(ctx context.Context, resource *v1alpha1.Localbuild, repoType, repoName, embeddedName, absPath string) (*v1alpha1.GitRepository, error) { repo := &v1alpha1.GitRepository{ ObjectMeta: metav1.ObjectMeta{ Name: repoName, Namespace: globals.GetProjectNamespace(resource.Name), }, } cliStartTime, err := util.GetCLIStartTimeAnnotationValue(resource.Annotations) if err != nil { return nil, err } _, err = controllerutil.CreateOrUpdate(ctx, r.Client, repo, func() error { if err := controllerutil.SetControllerReference(resource, repo, r.Scheme); err != nil { return err } if repo.ObjectMeta.Annotations == nil { repo.ObjectMeta.Annotations = make(map[string]string) } util.SetCLIStartTimeAnnotationValue(repo.ObjectMeta.Annotations, cliStartTime) repo.Spec = v1alpha1.GitRepositorySpec{ Source: v1alpha1.GitRepositorySource{ Type: repoType, }, Provider: v1alpha1.Provider{ Name: v1alpha1.GitProviderGitea, GitURL: resource.Status.Gitea.ExternalURL, InternalGitURL: resource.Status.Gitea.InternalURL, OrganizationName: v1alpha1.GiteaAdminUserName, }, SecretRef: v1alpha1.SecretReference{ Name: resource.Status.Gitea.AdminUserSecretName, Namespace: resource.Status.Gitea.AdminUserSecretNamespace, }, } if repoType == v1alpha1.SourceTypeEmbedded { repo.Spec.Source.EmbeddedAppName = embeddedName } else { repo.Spec.Source.Path = absPath } f, ok := resource.Spec.PackageConfigs.CorePackageCustomization[embeddedName] if ok { repo.Spec.Customization = v1alpha1.PackageCustomization{ Name: embeddedName, FilePath: f.FilePath, } } return nil }) return repo, err } func (r *LocalbuildReconciler) requestArgoCDAppRefresh(ctx context.Context) error { apps := &argov1alpha1.ApplicationList{} err := r.Client.List(ctx, apps, client.InNamespace(globals.ArgoCDNamespace)) if err != nil { return fmt.Errorf("listing argocd apps for refresh: %w", err) } apps: for i := range apps.Items { app := apps.Items[i] for _, o := range app.OwnerReferences { // if this app is owned by an ApplicationSet, we should let the ApplicationSet refresh. if o.Kind == argocdapp.ApplicationSetKind { continue apps } } aErr := r.applyArgoCDAnnotation(ctx, &app, argocdapp.ApplicationKind, argoCDApplicationAnnotationKeyRefresh, argoCDApplicationAnnotationValueRefreshNormal) if aErr != nil { return aErr } } return nil } func (r *LocalbuildReconciler) requestArgoCDAppSetRefresh(ctx context.Context) error { appsets := &argov1alpha1.ApplicationSetList{} err := r.Client.List(ctx, appsets, client.InNamespace(globals.ArgoCDNamespace)) if err != nil { return fmt.Errorf("listing argocd apps for refresh: %w", err) } for i := range appsets.Items { appset := appsets.Items[i] aErr := r.applyArgoCDAnnotation(ctx, &appset, argocdapp.ApplicationSetKind, argoCDApplicationSetAnnotationKeyRefresh, argoCDApplicationSetAnnotationKeyRefreshTrue) if aErr != nil { return aErr } } return nil } func (r *LocalbuildReconciler) extractArgocdInitialAdminSecret(ctx context.Context) (string, error) { sec := util.ArgocdInitialAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), }, &sec) if err != nil { if k8serrors.IsNotFound(err) { return "", fmt.Errorf("initial admin secret not found") } } return string(sec.Data["password"]), nil } func (r *LocalbuildReconciler) extractGiteaAdminSecret(ctx context.Context) (string, error) { sec := util.GiteaAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), }, &sec) if err != nil { if k8serrors.IsNotFound(err) { return "", fmt.Errorf("gitea admin secret not found") } } return string(sec.Data["password"]), nil } func (r *LocalbuildReconciler) updateGiteaPassword(ctx context.Context, adminPassword string) error { giteaBaseUrl := util.GiteaBaseUrl(r.Config) client, err := gitea.NewClient(giteaBaseUrl, gitea.SetHTTPClient(util.GetHttpClient()), gitea.SetBasicAuth("giteaAdmin", adminPassword), gitea.SetContext(ctx), ) if err != nil { return fmt.Errorf("cannot create gitea client: %w", err) } opts := gitea.EditUserOption{ LoginName: "giteaAdmin", Password: util.StaticPassword, } resp, err := client.AdminEditUser("giteaAdmin", opts) if err != nil { return fmt.Errorf("cannot update gitea admin user. status: %d error : %w", resp.StatusCode, err) } err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.GiteaNamespace, util.GiteaAdminSecret, util.GiteaAdminName, util.StaticPassword) if err != nil { return fmt.Errorf("patching the gitea credentials failed : %w", err) } return nil } func (r *LocalbuildReconciler) updateArgocdPassword(ctx context.Context, adminPassword string) error { argocdBaseUrl := util.ArgocdBaseUrl(r.Config) argocdEndpoint := argocdBaseUrl + "/api/v1" payload := map[string]string{ "username": "admin", "password": adminPassword, } payloadBytes, err := json.Marshal(payload) if err != nil { return fmt.Errorf("Error creating JSON payload: %v\n", err) } // Create an HTTP POST request to get the Session token req, err := http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) if err != nil { return fmt.Errorf("Error creating HTTP request: %v\n", err) } req.Header.Set("Content-Type", "application/json") // Create an HTTP c and disable TLS verification c := util.GetHttpClient() // Send the request resp, err := c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() // Read the response body body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("Error reading response body: %v\n", err) } // We got a session Token, so we can update the Argocd admin password if resp.StatusCode == 200 { var argocdSession ArgocdSession err := json.Unmarshal([]byte(body), &argocdSession) if err != nil { return fmt.Errorf("Error unmarshalling JSON: %v", err) } payload := map[string]string{ "name": "admin", "currentPassword": adminPassword, "newPassword": util.StaticPassword, } payloadBytes, err := json.Marshal(payload) if err != nil { return fmt.Errorf("Error creating JSON payload: %v\n", err) } req, err := http.NewRequest("PUT", argocdEndpoint+"/account/password", bytes.NewBuffer(payloadBytes)) if req != nil { req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", argocdSession.Token)) req.Header.Set("Content-Type", "application/json") } resp, err := c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() // Lets checking the new admin password payload = map[string]string{ "username": "admin", "password": util.StaticPassword, } payloadBytes, err = json.Marshal(payload) if err != nil { return fmt.Errorf("Error creating JSON payload: %v\n", err) } // Define the request able to verify if the username and password changed works req, err = http.NewRequest("POST", argocdEndpoint+"/session", bytes.NewBuffer(payloadBytes)) if err != nil { return fmt.Errorf("Error creating HTTP request: %v\n", err) } req.Header.Set("Content-Type", "application/json") // Send the request resp, err = c.Do(req) if err != nil { return fmt.Errorf("Error sending request: %v\n", err) } defer resp.Body.Close() // Password verification succeeded ! if resp.StatusCode == 200 { // Let's patch the existing secret now err = util.PatchPasswordSecret(ctx, r.Client, r.Config, util.ArgocdNamespace, util.ArgocdInitialAdminSecretName, util.ArgocdAdminName, util.StaticPassword) if err != nil { return fmt.Errorf("patching the argocd initial secret failed : %w", err) } return nil } } // No session token has been received and by consequence the admin password has not been changed return nil } func (r *LocalbuildReconciler) applyArgoCDAnnotation(ctx context.Context, obj client.Object, argoCDType, annotationKey, annotationValue string) error { annotations := obj.GetAnnotations() if annotations != nil { _, ok := annotations[annotationKey] if !ok { annotations[annotationKey] = annotationValue err := util.ApplyAnnotation(ctx, r.Client, obj, annotations, client.FieldOwner(v1alpha1.FieldManager)) if err != nil { return fmt.Errorf("applying %s refresh annotation for %s: %w", argoCDType, obj.GetName(), err) } } } else { a := map[string]string{ annotationKey: annotationValue, } err := util.ApplyAnnotation(ctx, r.Client, obj, a, client.FieldOwner(v1alpha1.FieldManager)) if err != nil { return fmt.Errorf("applying %s refresh annotation for %s: %w", argoCDType, obj.GetName(), err) } } return nil } func getCustomPackageName(fileName, appName string) string { s := strings.Split(fileName, ".") return fmt.Sprintf("%s-%s", strings.ToLower(s[0]), appName) } func isSupportedArgoCDTypes(gvk *schema.GroupVersionKind) bool { if gvk == nil { return false } return gvk.Group == argocdapp.Group && (gvk.Kind == argocdapp.ApplicationKind || gvk.Kind == argocdapp.ApplicationSetKind) } func GetEmbeddedRawInstallResources(name string, templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { switch name { case v1alpha1.ArgoCDPackageName: return RawArgocdInstallResources(templateData, config, scheme) case v1alpha1.GiteaPackageName: return RawGiteaInstallResources(templateData, config, scheme) case v1alpha1.IngressNginxPackageName: return RawNginxInstallResources(templateData, config, scheme) default: return nil, fmt.Errorf("unsupported embedded app name %s", name) } } ================================================ FILE: pkg/controllers/localbuild/gitea.go ================================================ package localbuild import ( "context" "embed" "encoding/base64" "fmt" "github.com/cnoe-io/idpbuilder/pkg/k8s" "net/http" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/util" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) //go:embed resources/gitea/k8s/* var installGiteaFS embed.FS func RawGiteaInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { return k8s.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData) } func (r *LocalbuildReconciler) newGiteaAdminSecret(password string) corev1.Secret { obj := util.GiteaAdminSecretObject() obj.StringData = map[string]string{ "username": v1alpha1.GiteaAdminUserName, "password": password, } return obj } func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { logger := log.FromContext(ctx, "installer", "gitea") gitea := EmbeddedInstallation{ name: "Gitea", resourcePath: "resources/gitea/k8s", resourceFS: installGiteaFS, namespace: util.GiteaNamespace, monitoredResources: map[string]schema.GroupVersionKind{ "my-gitea": { Group: "apps", Version: "v1", Kind: "Deployment", }, }, } sec := util.GiteaAdminSecretObject() err := r.Client.Get(ctx, types.NamespacedName{ Namespace: sec.GetNamespace(), Name: sec.GetName(), }, &sec) if err != nil { if k8serrors.IsNotFound(err) { genPassword, err := util.GeneratePassword() if err != nil { return ctrl.Result{}, fmt.Errorf("generating gitea password: %w", err) } giteaCreds := r.newGiteaAdminSecret(genPassword) if err != nil { return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err) } gitea.unmanagedResources = []client.Object{&giteaCreds} sec = giteaCreds } else { return ctrl.Result{}, fmt.Errorf("getting gitea secret: %w", err) } } v, ok := resource.Spec.PackageConfigs.CorePackageCustomization[v1alpha1.GiteaPackageName] if ok { gitea.customization = v } if result, err := gitea.Install(ctx, resource, r.Client, r.Scheme, r.Config); err != nil { return result, err } baseUrl := util.GiteaBaseUrl(r.Config) // need this to ensure gitrepository controller can reach the api endpoint. logger.V(1).Info("checking gitea api endpoint", "url", baseUrl) c := util.GetHttpClient() resp, err := c.Get(baseUrl) if err != nil { return ctrl.Result{}, err } if resp != nil { resp.Body.Close() if resp.StatusCode != http.StatusOK { logger.V(1).Info("gitea manifests installed successfully. endpoint not ready", "statusCode", resp.StatusCode) return ctrl.Result{RequeueAfter: errRequeueTime}, nil } } err = r.setGiteaToken(ctx, sec, baseUrl) if err != nil { return ctrl.Result{}, fmt.Errorf("creating gitea token: %w", err) } resource.Status.Gitea.ExternalURL = baseUrl resource.Status.Gitea.InternalURL = util.GiteaBaseUrl(r.Config) resource.Status.Gitea.AdminUserSecretName = util.GiteaAdminSecret resource.Status.Gitea.AdminUserSecretNamespace = util.GiteaNamespace resource.Status.Gitea.Available = true return ctrl.Result{}, nil } func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1.Secret, baseUrl string) error { _, ok := secret.Data[util.GiteaAdminTokenFieldName] if ok { return nil } u := unstructured.Unstructured{} u.SetName(util.GiteaAdminSecret) u.SetNamespace(util.GiteaNamespace) u.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret")) user, ok := secret.Data["username"] if !ok { return fmt.Errorf("username field not found in gitea secret") } pass, ok := secret.Data["password"] if !ok { return fmt.Errorf("password field not found in gitea secret") } t, err := util.GetGiteaToken(ctx, baseUrl, string(user), string(pass)) if err != nil { return fmt.Errorf("getting gitea token: %w", err) } token := base64.StdEncoding.EncodeToString([]byte(t)) err = unstructured.SetNestedField(u.Object, token, "data", util.GiteaAdminTokenFieldName) if err != nil { return fmt.Errorf("setting gitea token field: %w", err) } return r.Client.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) } ================================================ FILE: pkg/controllers/localbuild/gitea_test.go ================================================ package localbuild import ( "context" "github.com/cnoe-io/idpbuilder/pkg/util" "net/http" "net/http/httptest" "testing" "time" "github.com/stretchr/testify/require" ) func TestGetGiteaToken(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(time.Second * 35) })) defer ts.Close() ctx := context.Background() _, err := util.GetGiteaToken(ctx, ts.URL, "", "") require.Error(t, err) } ================================================ FILE: pkg/controllers/localbuild/installer.go ================================================ package localbuild import ( "context" "embed" "errors" "fmt" "sync" "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/k8s" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) var timeout = time.After(5 * time.Minute) type EmbeddedInstallation struct { name string resourcePath string namespace string // skips waiting on expected resources to become ready skipReadinessCheck bool // name and gvk pair for resources that need to be monitored monitoredResources map[string]schema.GroupVersionKind customization v1alpha1.PackageCustomization resourceFS embed.FS // resources that need to be created without using static manifests or gitops unmanagedResources []client.Object } func (e *EmbeddedInstallation) installResources(scheme *runtime.Scheme, templateData any) ([]client.Object, error) { return k8s.BuildCustomizedObjects(e.customization.FilePath, e.resourcePath, e.resourceFS, scheme, templateData) } func (e *EmbeddedInstallation) newNamespace(namespace string) *corev1.Namespace { return &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: namespace, }, } } func (e *EmbeddedInstallation) Install(ctx context.Context, resource *v1alpha1.Localbuild, cli client.Client, sc *runtime.Scheme, cfg v1alpha1.BuildCustomizationSpec) (ctrl.Result, error) { logger := log.FromContext(ctx) nsClient := client.NewNamespacedClient(cli, e.namespace) installObjs, err := e.installResources(sc, cfg) if err != nil { return ctrl.Result{}, err } if err = k8s.EnsureNamespace(ctx, nsClient, e.namespace); err != nil { return ctrl.Result{}, err } for i := range e.unmanagedResources { err = k8s.EnsureObject(ctx, nsClient, e.unmanagedResources[i], e.namespace) if err != nil { return ctrl.Result{}, err } } sch := runtime.NewScheme() appsv1.AddToScheme(sch) for _, obj := range installObjs { // Create object if err = k8s.EnsureObject(ctx, nsClient, obj, e.namespace); err != nil { return ctrl.Result{}, err } } // return early if readiness check is disabled if e.skipReadinessCheck { return ctrl.Result{}, nil } // wait for expected resources to become available errCh := make(chan error) var wg sync.WaitGroup for _, obj := range installObjs { if gvk, ok := e.monitoredResources[obj.GetName()]; ok { if obj.GetObjectKind().GroupVersionKind() != gvk { continue } wg.Add(1) go func(obj client.Object, gvk schema.GroupVersionKind) { defer wg.Done() gvkObj, err := sch.New(gvk) if err != nil { errCh <- err return } for { if gotObj, ok := gvkObj.(client.Object); ok { if err := cli.Get(ctx, types.NamespacedName{Namespace: e.namespace, Name: obj.GetName()}, gotObj); err != nil { errCh <- err return } switch t := gotObj.(type) { case *appsv1.Deployment: if t.Status.AvailableReplicas >= 1 { logger.V(1).Info(t.GetName(), "deployment", t.Status.AvailableReplicas) return } case *appsv1.StatefulSet: if t.Status.AvailableReplicas >= 1 { logger.V(1).Info(t.GetName(), "statefulset", t.Status.AvailableReplicas) return } } } logger.Info(fmt.Sprintf("Waiting for %s %s to become ready", gvk.Kind, obj.GetName())) time.Sleep(30 * time.Second) } }(obj, gvk) } } go func() { wg.Wait() close(errCh) }() select { case <-timeout: err := errors.New("Timeout") logger.Error(err, fmt.Sprintf("Didn't reconcile %s on time", e.name)) return ctrl.Result{}, err case err, errOccurred := <-errCh: if !errOccurred { logger.V(1).Info(fmt.Sprintf("%s is ready!", e.name)) } else { logger.Error(err, fmt.Sprintf("failed to reconcile the %s resources", e.name)) return ctrl.Result{}, err } } return ctrl.Result{}, nil } ================================================ FILE: pkg/controllers/localbuild/nginx.go ================================================ package localbuild import ( "context" "embed" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/globals" "github.com/cnoe-io/idpbuilder/pkg/k8s" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" ) //go:embed resources/nginx/k8s/* var installNginxFS embed.FS func RawNginxInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) { return k8s.BuildCustomizedManifests(config.FilePath, "resources/nginx/k8s", installNginxFS, scheme, templateData) } func (r *LocalbuildReconciler) ReconcileNginx(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) { nginx := EmbeddedInstallation{ name: "Nginx", resourcePath: "resources/nginx/k8s", resourceFS: installNginxFS, namespace: globals.NginxNamespace, monitoredResources: map[string]schema.GroupVersionKind{ "ingress-nginx-controller": { Group: "apps", Version: "v1", Kind: "Deployment", }, }, } v, ok := resource.Spec.PackageConfigs.CorePackageCustomization[v1alpha1.IngressNginxPackageName] if ok { nginx.customization = v } if result, err := nginx.Install(ctx, resource, r.Client, r.Scheme, r.Config); err != nil { return result, err } resource.Status.Nginx.Available = true return ctrl.Result{}, nil } ================================================ FILE: pkg/controllers/localbuild/resources/argo/ingress.yaml ================================================ {{- if .UsePathRouting -}} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-server-ingress-http namespace: argocd annotations: nginx.ingress.kubernetes.io/backend-protocol: "HTTP" nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - path: /argocd(/|$)(.*) pathType: ImplementationSpecific backend: service: name: argocd-server port: name: http {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - path: /argocd(/|$)(.*) pathType: ImplementationSpecific backend: service: name: argocd-server port: name: http {{ end }} {{- else -}} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: argocd-server-ingress namespace: argocd annotations: nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/ssl-passthrough: "true" spec: ingressClassName: "nginx" rules: - host: argocd.{{ .IngressHost }} http: paths: - path: / pathType: Prefix backend: service: name: argocd-server port: name: https {{- if ne .IngressHost .Host }} - host: argocd.{{ .Host }} http: paths: - path: / pathType: Prefix backend: service: name: argocd-server port: name: https {{ end }} {{ end }} ================================================ FILE: pkg/controllers/localbuild/resources/argo/install.yaml ================================================ # UCP ARGO INSTALL RESOURCES # This file is auto-generated with 'hack/argo-cd/generate-manifests.sh' apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applications.argoproj.io app.kubernetes.io/part-of: argocd name: applications.argoproj.io spec: group: argoproj.io names: kind: Application listKind: ApplicationList plural: applications shortNames: - app - apps singular: application scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .status.sync.status name: Sync Status type: string - jsonPath: .status.health.status name: Health Status type: string - jsonPath: .status.sync.revision name: Revision priority: 10 type: string - jsonPath: .spec.project name: Project priority: 10 type: string name: v1alpha1 schema: openAPIV3Schema: description: Application is a definition of Application resource. 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 operation: description: Operation contains information about a requested or running operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: autoHealAttemptsCount: description: SelfHealAttemptsCount contains the number of auto-heal attempts format: int64 type: integer dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: |- Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: |- Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: |- Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: |- Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: |- Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: |- Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object spec: description: ApplicationSpec represents desired application state. Contains link to repository with application definition and additional parameters link definition revision. properties: destination: description: Destination is a reference to the target Kubernetes server and namespace properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name. This must be set if Server is not set. type: string namespace: description: |- Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster's Kubernetes control plane API. This must be set if Name is not set. type: string type: object ignoreDifferences: description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: |- ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: description: Info contains a list of information (URLs, email addresses, and plain text) that relates to the application items: properties: name: type: string value: type: string required: - name - value type: object type: array project: description: |- Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project. type: string revisionHistoryLimit: description: |- RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions. This should only be changed in exceptional circumstances. Setting to zero will store no history. This will reduce storage used. Increasing will increase the space used to store the history, so we do not recommend increasing it. Default is 10. format: int64 type: integer source: description: Source is a reference to the location of the application's manifests or chart properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sourceHydrator: description: SourceHydrator provides a way to push hydrated manifests back to git before syncing them to the cluster. properties: drySource: description: DrySource specifies where the dry "don't repeat yourself" manifest source lives. properties: path: description: Path is a directory path within the Git repository where the manifests are located type: string repoURL: description: RepoURL is the URL to the git repository that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to hydrate type: string required: - path - repoURL - targetRevision type: object hydrateTo: description: |- HydrateTo specifies an optional "staging" location to push hydrated manifests to. An external system would then have to move manifests to the SyncSource, e.g. by pull request. properties: targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - targetBranch type: object syncSource: description: SyncSource specifies where to sync hydrated manifests from. properties: path: description: |- Path is a directory path within the git repository where hydrated manifests should be committed to and synced from. If hydrateTo is set, this is just the path from which hydrated manifests will be synced. type: string targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: description: Sources is a reference to the location of the application's manifests or chart items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncPolicy: description: SyncPolicy controls when and how a sync will be performed properties: automated: description: Automated will keep an application synced to the target revision properties: allowEmpty: description: 'AllowEmpty allows apps have zero live resources (default: false)' type: boolean enabled: description: Enable allows apps to explicitly control automated sync type: boolean prune: description: 'Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false)' type: boolean selfHeal: description: 'SelfHeal specifies whether to revert resources back to their desired state upon modification in the cluster (default: false)' type: boolean type: object managedNamespaceMetadata: description: ManagedNamespaceMetadata controls metadata in the given namespace (if CreateNamespace=true) properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: description: Retry controls failed sync retry behavior properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object syncOptions: description: Options allow you to specify whole app sync-options items: type: string type: array type: object required: - destination - project type: object status: description: ApplicationStatus contains status information for the application properties: conditions: description: Conditions is a list of currently observed application conditions items: description: ApplicationCondition contains details about an application condition, which is usually an error or warning properties: lastTransitionTime: description: LastTransitionTime is the time the condition was last observed format: date-time type: string message: description: Message contains human-readable message indicating details about condition type: string type: description: Type is an application condition type type: string required: - message - type type: object type: array controllerNamespace: description: ControllerNamespace indicates the namespace in which the application controller is located type: string health: description: Health contains information about the application's current health status properties: lastTransitionTime: description: LastTransitionTime is the time the HealthStatus was set or updated format: date-time type: string message: description: |- Message is a human-readable informational message describing the health status Deprecated: this field is not used and will be removed in a future release. type: string status: description: Status holds the status code of the application type: string type: object history: description: History contains information about the application's sync history items: description: RevisionHistory contains history information about a previous sync properties: deployStartedAt: description: DeployStartedAt holds the time the sync operation started format: date-time type: string deployedAt: description: DeployedAt holds the time the sync operation completed format: date-time type: string id: description: ID is an auto incrementing identifier of the RevisionHistory format: int64 type: integer initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object revision: description: Revision holds the revision the sync was performed against type: string revisions: description: Revisions holds the revision of each source in sources field the sync was performed against items: type: string type: array source: description: Source is a reference to the application source used for the sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application sources used for the sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - deployedAt - id type: object type: array observedAt: description: |- ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field format: date-time type: string operationState: description: OperationState contains information about any ongoing operations, such as a sync properties: finishedAt: description: FinishedAt contains time of operation completion format: date-time type: string message: description: Message holds any pertinent messages when attempting to perform operation (typically errors). type: string operation: description: Operation is the original requested operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: autoHealAttemptsCount: description: SelfHealAttemptsCount contains the number of auto-heal attempts format: int64 type: integer dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: |- Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: |- Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: |- Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: |- Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: |- Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: |- Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object phase: description: Phase is the current phase of the operation type: string retryCount: description: RetryCount contains time of operation retries format: int64 type: integer startedAt: description: StartedAt contains time of operation start format: date-time type: string syncResult: description: SyncResult is the result of a Sync operation properties: managedNamespaceMetadata: description: ManagedNamespaceMetadata contains the current sync state of managed namespace metadata properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object resources: description: Resources contains a list of sync result items for each individual resource in a sync operation items: description: ResourceResult holds the operation result details of a specific resource properties: group: description: Group specifies the API group of the resource type: string hookPhase: description: |- HookPhase contains the state of any operation associated with this resource OR hook This can also contain values for non-hook resources. type: string hookType: description: HookType specifies the type of the hook. Empty for non-hook resources type: string images: description: Images contains the images related to the ResourceResult items: type: string type: array kind: description: Kind specifies the API kind of the resource type: string message: description: Message contains an informational or error message for the last sync OR operation type: string name: description: Name specifies the name of the resource type: string namespace: description: Namespace specifies the target namespace of the resource type: string status: description: Status holds the final result of the sync. Will be empty if the resources is yet to be applied/pruned and is always zero-value for hooks type: string syncPhase: description: SyncPhase indicates the particular phase of the sync that this result was acquired in type: string version: description: Version specifies the API version of the resource type: string required: - group - kind - name - namespace - version type: object type: array revision: description: Revision holds the revision this sync operation was performed to type: string revisions: description: Revisions holds the revision this sync operation was performed for respective indexed source in sources field items: type: string type: array source: description: Source records the application source information of the sync, used for comparing auto-sync properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Source records the application source information of the sync, used for comparing auto-sync items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - revision type: object required: - operation - phase - startedAt type: object reconciledAt: description: ReconciledAt indicates when the application state was reconciled using the latest git version format: date-time type: string resourceHealthSource: description: 'ResourceHealthSource indicates where the resource health status is stored: inline if not set or appTree' type: string resources: description: Resources is a list of Kubernetes resources managed by this application items: description: ResourceStatus holds the current synchronization and health status of a Kubernetes resource. properties: group: description: Group represents the API group of the resource (e.g., "apps" for Deployments). type: string health: description: Health indicates the health status of the resource (e.g., Healthy, Degraded, Progressing). properties: lastTransitionTime: description: |- LastTransitionTime is the time the HealthStatus was set or updated Deprecated: this field is not used and will be removed in a future release. format: date-time type: string message: description: Message is a human-readable informational message describing the health status type: string status: description: Status holds the status code of the resource type: string type: object hook: description: Hook is true if the resource is used as a lifecycle hook in an Argo CD application. type: boolean kind: description: Kind specifies the type of the resource (e.g., "Deployment", "Service"). type: string name: description: Name is the unique name of the resource within the namespace. type: string namespace: description: Namespace defines the Kubernetes namespace where the resource is located. type: string requiresDeletionConfirmation: description: RequiresDeletionConfirmation is true if the resource requires explicit user confirmation before deletion. type: boolean requiresPruning: description: RequiresPruning is true if the resource needs to be pruned (deleted) as part of synchronization. type: boolean status: description: Status represents the synchronization state of the resource (e.g., Synced, OutOfSync). type: string syncWave: description: |- SyncWave determines the order in which resources are applied during a sync operation. Lower values are applied first. format: int64 type: integer version: description: Version indicates the API version of the resource (e.g., "v1", "v1beta1"). type: string type: object type: array sourceHydrator: description: SourceHydrator stores information about the current state of source hydration properties: currentOperation: description: CurrentOperation holds the status of the hydrate operation properties: drySHA: description: DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation type: string finishedAt: description: FinishedAt indicates when the hydrate operation finished format: date-time type: string hydratedSHA: description: HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation type: string message: description: Message contains a message describing the current status of the hydrate operation type: string phase: description: Phase indicates the status of the hydrate operation enum: - Hydrating - Failed - Hydrated type: string sourceHydrator: description: SourceHydrator holds the hydrator config used for the hydrate operation properties: drySource: description: DrySource specifies where the dry "don't repeat yourself" manifest source lives. properties: path: description: Path is a directory path within the Git repository where the manifests are located type: string repoURL: description: RepoURL is the URL to the git repository that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to hydrate type: string required: - path - repoURL - targetRevision type: object hydrateTo: description: |- HydrateTo specifies an optional "staging" location to push hydrated manifests to. An external system would then have to move manifests to the SyncSource, e.g. by pull request. properties: targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - targetBranch type: object syncSource: description: SyncSource specifies where to sync hydrated manifests from. properties: path: description: |- Path is a directory path within the git repository where hydrated manifests should be committed to and synced from. If hydrateTo is set, this is just the path from which hydrated manifests will be synced. type: string targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object startedAt: description: StartedAt indicates when the hydrate operation started format: date-time type: string required: - message - phase type: object lastSuccessfulOperation: description: LastSuccessfulOperation holds info about the most recent successful hydration properties: drySHA: description: DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation type: string hydratedSHA: description: HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation type: string sourceHydrator: description: SourceHydrator holds the hydrator config used for the hydrate operation properties: drySource: description: DrySource specifies where the dry "don't repeat yourself" manifest source lives. properties: path: description: Path is a directory path within the Git repository where the manifests are located type: string repoURL: description: RepoURL is the URL to the git repository that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to hydrate type: string required: - path - repoURL - targetRevision type: object hydrateTo: description: |- HydrateTo specifies an optional "staging" location to push hydrated manifests to. An external system would then have to move manifests to the SyncSource, e.g. by pull request. properties: targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - targetBranch type: object syncSource: description: SyncSource specifies where to sync hydrated manifests from. properties: path: description: |- Path is a directory path within the git repository where hydrated manifests should be committed to and synced from. If hydrateTo is set, this is just the path from which hydrated manifests will be synced. type: string targetBranch: description: TargetBranch is the branch to which hydrated manifests should be committed type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object type: object type: object sourceType: description: SourceType specifies the type of this application type: string sourceTypes: description: SourceTypes specifies the type of the sources included in the application items: description: ApplicationSourceType specifies the type of the application's source type: string type: array summary: description: Summary contains a list of URLs and container images used by this application properties: externalURLs: description: ExternalURLs holds all external URLs of application child resources. items: type: string type: array images: description: Images holds all images of application child resources. items: type: string type: array type: object sync: description: Sync contains information about the application's current sync status properties: comparedTo: description: ComparedTo contains information about what has been compared properties: destination: description: Destination is a reference to the application's destination used for comparison properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name. This must be set if Server is not set. type: string namespace: description: |- Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster's Kubernetes control plane API. This must be set if Name is not set. type: string type: object ignoreDifferences: description: IgnoreDifferences is a reference to the application's ignored differences used for comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: |- ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array source: description: Source is a reference to the application's source used for comparison properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application's multiple sources used for comparison items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string namespace: description: Namespace is an optional namespace to template with. If left empty, defaults to the app's destination namespace. type: string parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean skipSchemaValidation: description: SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation) type: boolean skipTests: description: SkipTests skips test manifest installation step (Helm's --skip-tests). type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: apiVersions: description: |- APIVersions specifies the Kubernetes resource API versions to pass to Helm when templating manifests. By default, Argo CD uses the API versions of the target cluster. The format is [group/]version/kind. items: type: string type: array commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object components: description: Components specifies a list of kustomize components to add to the kustomization before building items: type: string type: array forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean ignoreMissingComponents: description: IgnoreMissingComponents prevents kustomize from failing when components do not exist locally by not appending them to kustomization file type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array kubeVersion: description: |- KubeVersion specifies the Kubernetes API version to pass to Helm when templating manifests. By default, Argo CD uses the Kubernetes version of the target cluster. type: string labelIncludeTemplates: description: LabelIncludeTemplates specifies whether to apply common labels to resource templates or not type: boolean labelWithoutSelector: description: LabelWithoutSelector specifies whether to apply common labels to resource selectors or not type: boolean namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string patches: description: Patches is a list of Kustomize patches items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object name: description: Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications. type: string path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: |- TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - destination type: object revision: description: Revision contains information about the revision the comparison has been performed to type: string revisions: description: Revisions contains information about the revisions of multiple sources the comparison has been performed to items: type: string type: array status: description: Status is the sync state of the comparison type: string required: - status type: object type: object required: - metadata - spec type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applicationsets.argoproj.io app.kubernetes.io/part-of: argocd name: applicationsets.argoproj.io spec: group: argoproj.io names: kind: ApplicationSet listKind: ApplicationSetList plural: applicationsets shortNames: - appset - appsets singular: applicationset scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: properties: apiVersion: type: string kind: type: string metadata: type: object spec: properties: applyNestedSelectors: type: boolean generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: flatList: type: boolean selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object matrix: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: flatList: type: boolean selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object group: type: string includeSharedProjects: type: boolean includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object topic: type: string required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic type: object type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators type: object merge: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: flatList: type: boolean selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object group: type: string includeSharedProjects: type: boolean includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object topic: type: string required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic type: object type: array mergeKeys: items: type: string type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators - mergeKeys type: object plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object insecure: type: boolean project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string caRef: properties: configMapName: type: string key: type: string required: - configMapName - key type: object group: type: string includeSharedProjects: type: boolean includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object topic: type: string required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string type: object type: object x-kubernetes-map-type: atomic type: object type: array goTemplate: type: boolean goTemplateOptions: items: type: string type: array ignoreApplicationDifferences: items: properties: jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array name: type: string type: object type: array preservedFields: properties: annotations: items: type: string type: array labels: items: type: string type: array type: object strategy: properties: rollingSync: properties: steps: items: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array type: object type: array maxUpdate: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true type: object type: array type: object type: type: string type: object syncPolicy: properties: applicationsSync: enum: - create-only - create-update - create-delete - sync type: string preserveResourcesOnDeletion: type: boolean type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sourceHydrator: properties: drySource: properties: path: type: string repoURL: type: string targetRevision: type: string required: - path - repoURL - targetRevision type: object hydrateTo: properties: targetBranch: type: string required: - targetBranch type: object syncSource: properties: path: type: string targetBranch: type: string required: - path - targetBranch type: object required: - drySource - syncSource type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: apiVersions: items: type: string type: array fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean kubeVersion: type: string namespace: type: string parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean skipSchemaValidation: type: boolean skipTests: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: apiVersions: items: type: string type: array commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object components: items: type: string type: array forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean ignoreMissingComponents: type: boolean images: items: type: string type: array kubeVersion: type: string labelIncludeTemplates: type: boolean labelWithoutSelector: type: boolean namePrefix: type: string nameSuffix: type: string namespace: type: string patches: items: properties: options: additionalProperties: type: boolean type: object patch: type: string path: type: string target: properties: annotationSelector: type: string group: type: string kind: type: string labelSelector: type: string name: type: string namespace: type: string version: type: string type: object type: object type: array replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object name: type: string path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean enabled: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object templatePatch: type: string required: - generators - template type: object status: properties: applicationStatus: items: properties: application: type: string lastTransitionTime: format: date-time type: string message: type: string status: type: string step: type: string targetRevisions: items: type: string type: array required: - application - message - status - step - targetRevisions type: object type: array conditions: items: properties: lastTransitionTime: format: date-time type: string message: type: string reason: type: string status: type: string type: type: string required: - message - reason - status - type type: object type: array resources: items: properties: group: type: string health: properties: lastTransitionTime: format: date-time type: string message: type: string status: type: string type: object hook: type: boolean kind: type: string name: type: string namespace: type: string requiresDeletionConfirmation: type: boolean requiresPruning: type: boolean status: type: string syncWave: format: int64 type: integer version: type: string type: object type: array type: object required: - metadata - spec type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: appprojects.argoproj.io app.kubernetes.io/part-of: argocd name: appprojects.argoproj.io spec: group: argoproj.io names: kind: AppProject listKind: AppProjectList plural: appprojects shortNames: - appproj - appprojs singular: appproject scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: |- AppProject provides a logical grouping of applications, providing controls for: * where the apps may deploy to (cluster whitelist) * what may be deployed (repository whitelist, resource whitelist/blacklist) * who can access these applications (roles, OIDC group claims bindings) * and what they can do (RBAC policies) * automation access to these roles (JWT tokens) properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: AppProjectSpec is the specification of an AppProject properties: clusterResourceBlacklist: description: ClusterResourceBlacklist contains list of blacklisted cluster level resources items: description: |- GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array clusterResourceWhitelist: description: ClusterResourceWhitelist contains list of whitelisted cluster level resources items: description: |- GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array description: description: Description contains optional project description maxLength: 255 type: string destinationServiceAccounts: description: DestinationServiceAccounts holds information about the service accounts to be impersonated for the application sync operation for each destination. items: description: ApplicationDestinationServiceAccount holds information about the service account to be impersonated for the application sync operation. properties: defaultServiceAccount: description: DefaultServiceAccount to be used for impersonation during the sync operation type: string namespace: description: Namespace specifies the target namespace for the application's resources. type: string server: description: Server specifies the URL of the target cluster's Kubernetes control plane API. type: string required: - defaultServiceAccount - server type: object type: array destinations: description: Destinations contains list of destinations available for deployment items: description: ApplicationDestination holds information about the application's destination properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name. This must be set if Server is not set. type: string namespace: description: |- Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster's Kubernetes control plane API. This must be set if Name is not set. type: string type: object type: array namespaceResourceBlacklist: description: NamespaceResourceBlacklist contains list of blacklisted namespace level resources items: description: |- GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array namespaceResourceWhitelist: description: NamespaceResourceWhitelist contains list of whitelisted namespace level resources items: description: |- GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array orphanedResources: description: OrphanedResources specifies if controller should monitor orphaned resources of apps in this project properties: ignore: description: Ignore contains a list of resources that are to be excluded from orphaned resources monitoring items: description: OrphanedResourceKey is a reference to a resource to be ignored from properties: group: type: string kind: type: string name: type: string type: object type: array warn: description: Warn indicates if warning condition should be created for apps which have orphaned resources type: boolean type: object permitOnlyProjectScopedClusters: description: PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped type: boolean roles: description: Roles are user defined RBAC roles associated with this project items: description: ProjectRole represents a role that has access to a project properties: description: description: Description is a description of the role type: string groups: description: Groups are a list of OIDC group claims bound to this role items: type: string type: array jwtTokens: description: JWTTokens are a list of generated JWT tokens bound to this role items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array name: description: Name is a name for this role type: string policies: description: Policies Stores a list of casbin formatted strings that define access policies for the role in the project items: type: string type: array required: - name type: object type: array signatureKeys: description: SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync items: description: SignatureKey is the specification of a key required to verify commit signatures with properties: keyID: description: The ID of the key in hexadecimal notation type: string required: - keyID type: object type: array sourceNamespaces: description: SourceNamespaces defines the namespaces application resources are allowed to be created in items: type: string type: array sourceRepos: description: SourceRepos contains list of repository URLs which can be used for deployment items: type: string type: array syncWindows: description: SyncWindows controls when syncs can be run for apps in this project items: description: SyncWindow contains the kind, time, duration and attributes that are used to assign the syncWindows to apps properties: andOperator: description: UseAndOperator use AND operator for matching applications, namespaces and clusters instead of the default OR operator type: boolean applications: description: Applications contains a list of applications that the window will apply to items: type: string type: array clusters: description: Clusters contains a list of clusters that the window will apply to items: type: string type: array description: description: Description of the sync that will be applied to the schedule, can be used to add any information such as a ticket number for example type: string duration: description: Duration is the amount of time the sync window will be open type: string kind: description: Kind defines if the window allows or blocks syncs type: string manualSync: description: ManualSync enables manual syncs when they would otherwise be blocked type: boolean namespaces: description: Namespaces contains a list of namespaces that the window will apply to items: type: string type: array schedule: description: Schedule is the time the window will begin, specified in cron format type: string timeZone: description: TimeZone of the sync that will be applied to the schedule type: string type: object type: array type: object status: description: AppProjectStatus contains status information for AppProject CRs properties: jwtTokensByRole: additionalProperties: description: JWTTokens represents a list of JWT tokens properties: items: items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array type: object description: JWTTokensByRole contains a list of JWT tokens issued for a given role type: object type: object required: - metadata - spec type: object served: true storage: true --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - argoproj.io resources: - applications - applicationsets - appprojects verbs: - create - get - list - watch - update - patch - delete - apiGroups: - "" resources: - events verbs: - create - list - apiGroups: - apps resources: - deployments verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller rules: - apiGroups: - argoproj.io resources: - applications - applicationsets - applicationsets/finalizers verbs: - create - delete - get - list - patch - update - watch - apiGroups: - argoproj.io resources: - appprojects verbs: - get - list - watch - apiGroups: - argoproj.io resources: - applicationsets/status verbs: - get - patch - update - apiGroups: - "" resources: - events verbs: - create - get - list - patch - watch - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - apps - extensions resources: - deployments verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller rules: - apiGroups: - argoproj.io resources: - applications - appprojects verbs: - get - list - watch - update - patch - apiGroups: - "" resources: - configmaps - secrets verbs: - list - watch - apiGroups: - "" resourceNames: - argocd-notifications-cm resources: - configmaps verbs: - get - apiGroups: - "" resourceNames: - argocd-notifications-secret resources: - secrets verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis rules: - apiGroups: - "" resourceNames: - argocd-redis resources: - secrets verbs: - get - apiGroups: - "" resources: - secrets verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - create - get - list - watch - update - patch - delete - apiGroups: - argoproj.io resources: - applications - appprojects - applicationsets verbs: - create - get - list - watch - update - delete - patch - apiGroups: - "" resources: - events verbs: - create - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - '*' resources: - '*' verbs: - '*' - nonResourceURLs: - '*' verbs: - '*' --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller rules: - apiGroups: - argoproj.io resources: - applications - applicationsets - applicationsets/finalizers verbs: - create - delete - get - list - patch - update - watch - apiGroups: - argoproj.io resources: - applicationsets/status verbs: - get - patch - update - apiGroups: - argoproj.io resources: - appprojects verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - get - list - patch - watch - apiGroups: - "" resources: - configmaps verbs: - create - update - delete - get - list - patch - watch - apiGroups: - "" resources: - secrets verbs: - get - list - watch - apiGroups: - apps - extensions resources: - deployments verbs: - get - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - delete - get - list - patch - update - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - '*' resources: - '*' verbs: - delete - get - patch - apiGroups: - "" resources: - events verbs: - list - apiGroups: - "" resources: - pods - pods/log verbs: - get - apiGroups: - argoproj.io resources: - applications - applicationsets verbs: - get - list - watch - apiGroups: - batch resources: - jobs verbs: - create - apiGroups: - argoproj.io resources: - workflows verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-applicationset-controller subjects: - kind: ServiceAccount name: argocd-applicationset-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-dex-server subjects: - kind: ServiceAccount name: argocd-dex-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-notifications-controller subjects: - kind: ServiceAccount name: argocd-notifications-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-redis subjects: - kind: ServiceAccount name: argocd-redis --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-server subjects: - kind: ServiceAccount name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller namespace: argocd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-applicationset-controller subjects: - kind: ServiceAccount name: argocd-applicationset-controller namespace: argocd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-server subjects: - kind: ServiceAccount name: argocd-server namespace: argocd --- apiVersion: v1 data: accounts.developer: apiKey, login application.resourceTrackingMethod: annotation resource.customizations.ignoreResourceUpdates.ConfigMap: | jqPathExpressions: # Ignore the cluster-autoscaler status - '.metadata.annotations."cluster-autoscaler.kubernetes.io/last-updated"' # Ignore the annotation of the legacy Leases election - '.metadata.annotations."control-plane.alpha.kubernetes.io/leader"' resource.customizations.ignoreResourceUpdates.Endpoints: | jsonPointers: - /metadata - /subsets resource.customizations.ignoreResourceUpdates.all: | jsonPointers: - /status resource.customizations.ignoreResourceUpdates.apps_ReplicaSet: | jqPathExpressions: - '.metadata.annotations."deployment.kubernetes.io/desired-replicas"' - '.metadata.annotations."deployment.kubernetes.io/max-replicas"' - '.metadata.annotations."rollout.argoproj.io/desired-replicas"' resource.customizations.ignoreResourceUpdates.argoproj.io_Application: | jqPathExpressions: - '.metadata.annotations."notified.notifications.argoproj.io"' - '.metadata.annotations."argocd.argoproj.io/refresh"' - '.metadata.annotations."argocd.argoproj.io/hydrate"' - '.operation' resource.customizations.ignoreResourceUpdates.argoproj.io_Rollout: | jqPathExpressions: - '.metadata.annotations."notified.notifications.argoproj.io"' resource.customizations.ignoreResourceUpdates.autoscaling_HorizontalPodAutoscaler: | jqPathExpressions: - '.metadata.annotations."autoscaling.alpha.kubernetes.io/behavior"' - '.metadata.annotations."autoscaling.alpha.kubernetes.io/conditions"' - '.metadata.annotations."autoscaling.alpha.kubernetes.io/metrics"' - '.metadata.annotations."autoscaling.alpha.kubernetes.io/current-metrics"' resource.customizations.ignoreResourceUpdates.discovery.k8s.io_EndpointSlice: | jsonPointers: - /metadata - /endpoints - /ports resource.exclusions: | - kinds: - ProviderConfigUsage apiGroups: - "*" timeout.reconciliation: 60s kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd name: argocd-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cmd-params-cm app.kubernetes.io/part-of: argocd name: argocd-cmd-params-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-gpg-keys-cm app.kubernetes.io/part-of: argocd name: argocd-gpg-keys-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-cm --- apiVersion: v1 data: policy.csv: | p, role:developer, applications, *, *, allow g, developer, role:developer kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-rbac-cm app.kubernetes.io/part-of: argocd name: argocd-rbac-cm --- apiVersion: v1 data: ssh_known_hosts: | # This file was automatically generated by hack/update-ssh-known-hosts.sh. DO NOT EDIT [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl [ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE= bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M= github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-ssh-known-hosts-cm app.kubernetes.io/part-of: argocd name: argocd-ssh-known-hosts-cm --- apiVersion: v1 data: '{{.Host}}': | {{ .SelfSignedCert | indentNewLines 4 }} gitea.{{.Host}}: | {{ .SelfSignedCert | indentNewLines 4 }} kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-tls-certs-cm app.kubernetes.io/part-of: argocd name: argocd-tls-certs-cm --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-secret type: Opaque --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/name: argocd-secret app.kubernetes.io/part-of: argocd name: argocd-secret type: Opaque --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: ports: - name: webhook port: 7000 protocol: TCP targetPort: webhook - name: metrics port: 8080 protocol: TCP targetPort: metrics selector: app.kubernetes.io/name: argocd-applicationset-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: ports: - appProtocol: TCP name: http port: 5556 protocol: TCP targetPort: 5556 - name: grpc port: 5557 protocol: TCP targetPort: 5557 - name: metrics port: 5558 protocol: TCP targetPort: 5558 selector: app.kubernetes.io/name: argocd-dex-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: metrics app.kubernetes.io/name: argocd-metrics app.kubernetes.io/part-of: argocd name: argocd-metrics spec: ports: - name: metrics port: 8082 protocol: TCP targetPort: 8082 selector: app.kubernetes.io/name: argocd-application-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller-metrics app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-metrics spec: ports: - name: metrics port: 9001 protocol: TCP targetPort: 9001 selector: app.kubernetes.io/name: argocd-notifications-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: ports: - name: tcp-redis port: 6379 targetPort: 6379 selector: app.kubernetes.io/name: argocd-redis --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: ports: - name: server port: 8081 protocol: TCP targetPort: 8081 - name: metrics port: 8084 protocol: TCP targetPort: 8084 selector: app.kubernetes.io/name: argocd-repo-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: ports: - name: http port: 80 protocol: TCP targetPort: 8080 - name: https port: 443 protocol: TCP targetPort: 8080 selector: app.kubernetes.io/name: argocd-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server-metrics app.kubernetes.io/part-of: argocd name: argocd-server-metrics spec: ports: - name: metrics port: 8083 protocol: TCP targetPort: 8083 selector: app.kubernetes.io/name: argocd-server --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: selector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller template: metadata: labels: app.kubernetes.io/name: argocd-applicationset-controller spec: containers: - args: - /usr/local/bin/argocd-applicationset-controller env: - name: ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_ANNOTATIONS valueFrom: configMapKeyRef: key: applicationsetcontroller.global.preserved.annotations name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS valueFrom: configMapKeyRef: key: applicationsetcontroller.global.preserved.labels name: argocd-cmd-params-cm optional: true - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_LEADER_ELECTION valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.leader.election name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_POLICY valueFrom: configMapKeyRef: key: applicationsetcontroller.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.policy.override name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DEBUG valueFrom: configMapKeyRef: key: applicationsetcontroller.debug name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: applicationsetcontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: applicationsetcontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_LOG_FORMAT_TIMESTAMP valueFrom: configMapKeyRef: key: log.format.timestamp name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DRY_RUN valueFrom: configMapKeyRef: key: applicationsetcontroller.dryrun name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.progressive.syncs name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_TOKENREF_STRICT_MODE valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.tokenref.strict.mode name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_NEW_GIT_FILE_GLOBBING valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.new.git.file.globbing name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_RECONCILIATIONS valueFrom: configMapKeyRef: key: applicationsetcontroller.concurrent.reconciliations.max name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_NAMESPACES valueFrom: configMapKeyRef: key: applicationsetcontroller.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH valueFrom: configMapKeyRef: key: applicationsetcontroller.scm.root.ca.path name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.allowed.scm.providers name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.scm.providers name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_GITHUB_API_METRICS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.github.api.metrics name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_WEBHOOK_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: applicationsetcontroller.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER valueFrom: configMapKeyRef: key: applicationsetcontroller.requeue.after name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT valueFrom: configMapKeyRef: key: applicationsetcontroller.status.max.resources.count name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent name: argocd-applicationset-controller ports: - containerPort: 7000 name: webhook - containerPort: 8080 name: metrics securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /tmp name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls nodeSelector: kubernetes.io/os: linux serviceAccountName: argocd-applicationset-controller volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-dex-server template: metadata: labels: app.kubernetes.io/name: argocd-dex-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - command: - /shared/argocd-dex - rundex env: - name: ARGOCD_DEX_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: dexserver.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEX_SERVER_LOGLEVEL valueFrom: configMapKeyRef: key: dexserver.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_LOG_FORMAT_TIMESTAMP valueFrom: configMapKeyRef: key: log.format.timestamp name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEX_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: dexserver.disable.tls name: argocd-cmd-params-cm optional: true image: ghcr.io/dexidp/dex:v2.43.0 imagePullPolicy: IfNotPresent name: dex ports: - containerPort: 5556 - containerPort: 5557 - containerPort: 5558 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig - mountPath: /tls name: argocd-dex-server-tls initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /shared/argocd-dex image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig nodeSelector: kubernetes.io/os: linux serviceAccountName: argocd-dex-server volumes: - emptyDir: {} name: static-files - emptyDir: {} name: dexconfig - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: argocd-notifications-controller spec: containers: - args: - /usr/local/bin/argocd-notifications env: - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: notificationscontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_LOG_FORMAT_TIMESTAMP valueFrom: configMapKeyRef: key: log.format.timestamp name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_NOTIFICATION_CONTROLLER_SELF_SERVICE_NOTIFICATION_ENABLED valueFrom: configMapKeyRef: key: notificationscontroller.selfservice.enabled name: argocd-cmd-params-cm optional: true - name: ARGOCD_NOTIFICATION_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: notificationscontroller.repo.server.plaintext name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent livenessProbe: tcpSocket: port: 9001 name: argocd-notifications-controller securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true volumeMounts: - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: selector: matchLabels: app.kubernetes.io/name: argocd-redis template: metadata: labels: app.kubernetes.io/name: argocd-redis spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-redis topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - --save - "" - --appendonly - "no" - --requirepass $(REDIS_PASSWORD) env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: key: auth name: argocd-redis image: public.ecr.aws/docker/library/redis:7.2.7-alpine imagePullPolicy: IfNotPresent name: redis ports: - containerPort: 6379 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true initContainers: - command: - argocd - admin - redis-initial-password image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent name: secret-init securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true runAsUser: 999 seccompProfile: type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-repo-server template: metadata: labels: app.kubernetes.io/name: argocd-repo-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 automountServiceAccountToken: false containers: - args: - /usr/local/bin/argocd-repo-server env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: key: auth name: argocd-redis - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_REPO_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: reposerver.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LOGLEVEL valueFrom: configMapKeyRef: key: reposerver.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_LOG_FORMAT_TIMESTAMP valueFrom: configMapKeyRef: key: log.format.timestamp name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: reposerver.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: reposerver.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_METRICS_ADDRESS valueFrom: configMapKeyRef: key: reposerver.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: reposerver.disable.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: reposerver.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.repo.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_INSECURE valueFrom: configMapKeyRef: key: otlp.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_HEADERS valueFrom: configMapKeyRef: key: otlp.headers name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_ATTRS valueFrom: configMapKeyRef: key: otlp.attrs name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE valueFrom: configMapKeyRef: key: reposerver.max.combined.directory.manifests.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS valueFrom: configMapKeyRef: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS valueFrom: configMapKeyRef: key: reposerver.plugin.use.manifest.generate.paths name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: key: reposerver.allow.oob.symlinks name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_TAR_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.tar.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.disable.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OCI_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.oci.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_OCI_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.disable.oci.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OCI_LAYER_MEDIA_TYPES valueFrom: configMapKeyRef: key: reposerver.oci.layer.media.types name: argocd-cmd-params-cm optional: true - name: ARGOCD_REVISION_CACHE_LOCK_TIMEOUT valueFrom: configMapKeyRef: key: reposerver.revision.cache.lock.timeout name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: reposerver.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_LS_REMOTE_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: reposerver.git.lsremote.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_REQUEST_TIMEOUT valueFrom: configMapKeyRef: key: reposerver.git.request.timeout name: argocd-cmd-params-cm optional: true - name: ARGOCD_GRPC_MAX_SIZE_MB valueFrom: configMapKeyRef: key: reposerver.grpc.max.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_INCLUDE_HIDDEN_DIRECTORIES valueFrom: configMapKeyRef: key: reposerver.include.hidden.directories name: argocd-cmd-params-cm optional: true - name: HELM_CACHE_HOME value: /helm-working-dir - name: HELM_CONFIG_HOME value: /helm-working-dir - name: HELM_DATA_HOME value: /helm-working-dir image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /healthz?full=true port: 8084 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 name: argocd-repo-server ports: - containerPort: 8081 - containerPort: 8084 readinessProbe: httpGet: path: /healthz port: 8084 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls - mountPath: /tmp name: tmp - mountPath: /helm-working-dir name: helm-working-dir - mountPath: /home/argocd/cmp-server/plugins name: plugins initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /var/run/argocd/argocd-cmp-server image: quay.io/argoproj/argocd:v3.1.7 name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files nodeSelector: kubernetes.io/os: linux serviceAccountName: argocd-repo-server volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - emptyDir: {} name: helm-working-dir - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - emptyDir: {} name: var-files - emptyDir: {} name: plugins --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-server template: metadata: labels: app.kubernetes.io/name: argocd-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-server - '{{if .UsePathRouting}}' - --insecure - --basehref - /argocd - '{{end}}' env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: key: auth name: argocd-redis - name: ARGOCD_SERVER_INSECURE valueFrom: configMapKeyRef: key: server.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_BASEHREF valueFrom: configMapKeyRef: key: server.basehref name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ROOTPATH valueFrom: configMapKeyRef: key: server.rootpath name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: server.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOG_LEVEL valueFrom: configMapKeyRef: key: server.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER valueFrom: configMapKeyRef: key: server.dex.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DISABLE_AUTH valueFrom: configMapKeyRef: key: server.disable.auth name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_GZIP valueFrom: configMapKeyRef: key: server.enable.gzip name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: server.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_X_FRAME_OPTIONS valueFrom: configMapKeyRef: key: server.x.frame.options name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONTENT_SECURITY_POLICY valueFrom: configMapKeyRef: key: server.content.security.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.dex.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.dex.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: server.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: server.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: server.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONNECTION_STATUS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.connection.status.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OIDC_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.oidc.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_STATIC_ASSETS valueFrom: configMapKeyRef: key: server.staticassets name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_MAX_COOKIE_NUMBER valueFrom: configMapKeyRef: key: server.http.cookie.maxnumber name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_METRICS_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_INSECURE valueFrom: configMapKeyRef: key: otlp.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_HEADERS valueFrom: configMapKeyRef: key: otlp.headers name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_ATTRS valueFrom: configMapKeyRef: key: otlp.attrs name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_PROXY_EXTENSION valueFrom: configMapKeyRef: key: server.enable.proxy.extension name: argocd-cmd-params-cm optional: true - name: ARGOCD_K8SCLIENT_RETRY_MAX valueFrom: configMapKeyRef: key: server.k8sclient.retry.max name: argocd-cmd-params-cm optional: true - name: ARGOCD_K8SCLIENT_RETRY_BASE_BACKOFF valueFrom: configMapKeyRef: key: server.k8sclient.retry.base.backoff name: argocd-cmd-params-cm optional: true - name: ARGOCD_API_CONTENT_TYPES valueFrom: configMapKeyRef: key: server.api.content.types name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_WEBHOOK_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: server.webhook.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_NEW_GIT_FILE_GLOBBING valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.new.git.file.globbing name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH valueFrom: configMapKeyRef: key: applicationsetcontroller.scm.root.ca.path name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.allowed.scm.providers name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.scm.providers name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_GITHUB_API_METRICS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.github.api.metrics name: argocd-cmd-params-cm optional: true - name: ARGOCD_HYDRATOR_ENABLED valueFrom: configMapKeyRef: key: hydrator.enabled name: argocd-cmd-params-cm optional: true - name: ARGOCD_SYNC_WITH_REPLACE_ALLOWED valueFrom: configMapKeyRef: key: server.sync.replace.allowed name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz?full=true port: 8080 initialDelaySeconds: 3 periodSeconds: 30 timeoutSeconds: 5 name: argocd-server ports: - containerPort: 8080 - containerPort: 8083 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 3 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/server/tls name: argocd-repo-server-tls - mountPath: /app/config/dex/tls name: argocd-dex-server-tls - mountPath: /home/argocd name: plugins-home - mountPath: /tmp name: tmp - mountPath: /home/argocd/params name: argocd-cmd-params-cm nodeSelector: kubernetes.io/os: linux serviceAccountName: argocd-server volumes: - emptyDir: {} name: plugins-home - emptyDir: {} name: tmp - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls - configMap: items: - key: server.profile.enabled path: profiler.enabled name: argocd-cmd-params-cm optional: true name: argocd-cmd-params-cm --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: argocd-application-controller serviceName: argocd-application-controller template: metadata: labels: app.kubernetes.io/name: argocd-application-controller spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-application-controller env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: key: auth name: argocd-redis - name: ARGOCD_CONTROLLER_REPLICAS value: "1" - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_HARD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.hard.reconciliation name: argocd-cm optional: true - name: ARGOCD_RECONCILIATION_JITTER valueFrom: configMapKeyRef: key: timeout.reconciliation.jitter name: argocd-cm optional: true - name: ARGOCD_REPO_ERROR_GRACE_PERIOD_SECONDS valueFrom: configMapKeyRef: key: controller.repo.error.grace.period.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_STATUS_PROCESSORS valueFrom: configMapKeyRef: key: controller.status.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OPERATION_PROCESSORS valueFrom: configMapKeyRef: key: controller.operation.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: controller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: controller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_LOG_FORMAT_TIMESTAMP valueFrom: configMapKeyRef: key: log.format.timestamp name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.metrics.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.backoff.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_FACTOR valueFrom: configMapKeyRef: key: controller.self.heal.backoff.factor name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_CAP_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.backoff.cap.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_COOLDOWN_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.backoff.cooldown.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SYNC_TIMEOUT valueFrom: configMapKeyRef: key: controller.sync.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: controller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: controller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_PERSIST_RESOURCE_HEALTH valueFrom: configMapKeyRef: key: controller.resource.health.persist name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_INSECURE valueFrom: configMapKeyRef: key: otlp.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_HEADERS valueFrom: configMapKeyRef: key: otlp.headers name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ATTRS valueFrom: configMapKeyRef: key: otlp.attrs name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_CONTROLLER_SHARDING_ALGORITHM valueFrom: configMapKeyRef: key: controller.sharding.algorithm name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_KUBECTL_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: controller.kubectl.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_K8SCLIENT_RETRY_MAX valueFrom: configMapKeyRef: key: controller.k8sclient.retry.max name: argocd-cmd-params-cm optional: true - name: ARGOCD_K8SCLIENT_RETRY_BASE_BACKOFF valueFrom: configMapKeyRef: key: controller.k8sclient.retry.base.backoff name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF valueFrom: configMapKeyRef: key: controller.diff.server.side name: argocd-cmd-params-cm optional: true - name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT valueFrom: configMapKeyRef: key: controller.ignore.normalizer.jq.timeout name: argocd-cmd-params-cm optional: true - name: ARGOCD_HYDRATOR_ENABLED valueFrom: configMapKeyRef: key: hydrator.enabled name: argocd-cmd-params-cm optional: true - name: ARGOCD_CLUSTER_CACHE_BATCH_EVENTS_PROCESSING valueFrom: configMapKeyRef: key: controller.cluster.cache.batch.events.processing name: argocd-cmd-params-cm optional: true - name: ARGOCD_CLUSTER_CACHE_EVENTS_PROCESSING_INTERVAL valueFrom: configMapKeyRef: key: controller.cluster.cache.events.processing.interval name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER valueFrom: configMapKeyRef: key: commit.server name: argocd-cmd-params-cm optional: true - name: KUBECACHEDIR value: /tmp/kubecache image: quay.io/argoproj/argocd:v3.1.7 imagePullPolicy: IfNotPresent name: argocd-application-controller ports: - containerPort: 8082 readinessProbe: httpGet: path: /healthz port: 8082 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls - mountPath: /home/argocd name: argocd-home - mountPath: /home/argocd/params name: argocd-cmd-params-cm - mountPath: /tmp name: argocd-application-controller-tmp workingDir: /home/argocd nodeSelector: kubernetes.io/os: linux serviceAccountName: argocd-application-controller volumes: - emptyDir: {} name: argocd-home - emptyDir: {} name: argocd-application-controller-tmp - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - configMap: items: - key: controller.profile.enabled path: profiler.enabled name: argocd-cmd-params-cm optional: true name: argocd-cmd-params-cm --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 8082 podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 7000 protocol: TCP - port: 8080 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server ports: - port: 5556 protocol: TCP - port: 5557 protocol: TCP - from: - namespaceSelector: {} ports: - port: 5558 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-dex-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 9001 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller ports: - port: 6379 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-redis policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller ports: - port: 8081 protocol: TCP - from: - namespaceSelector: {} ports: - port: 8084 podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server-network-policy spec: ingress: - {} podSelector: matchLabels: app.kubernetes.io/name: argocd-server policyTypes: - Ingress ================================================ FILE: pkg/controllers/localbuild/resources/gitea/k8s/install.yaml ================================================ # GITEA INSTALL RESOURCES # This file is auto-generated with 'hack/gitea/generate-manifests.sh' # Source: gitea/templates/gitea/config.yaml apiVersion: v1 kind: Secret metadata: name: my-gitea-inline-config namespace: gitea labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm type: Opaque stringData: _generals_: "" cache: |- ADAPTER=memory HOST= database: DB_TYPE=sqlite3 indexer: ISSUE_INDEXER_TYPE=db metrics: ENABLED=false queue: |- CONN_STR= TYPE=level repository: ROOT=/data/git/gitea-repositories security: INSTALL_LOCK=true server: |- APP_DATA_PATH=/data DOMAIN={{- if .UsePathRouting -}} {{ .Host }} {{- else -}} gitea.{{- .Host }} {{- end }} ENABLE_PPROF=false HTTP_PORT=3000 PROTOCOL=http ROOT_URL={{- if .UsePathRouting }} {{- .Protocol }}://{{ .Host }}:{{ .Port }}/gitea {{- else }} {{- .Protocol }}://gitea.{{ .Host }}:{{ .Port }} {{- end }} SSH_DOMAIN={{- if .UsePathRouting -}} {{ .Host }} {{- else -}} gitea.{{- .Host }} {{- end }} SSH_LISTEN_PORT=2222 SSH_PORT=32222 START_SSH_SERVER=true session: |- PROVIDER=memory PROVIDER_CONFIG= webhook: |- ALLOWED_HOST_LIST=private SKIP_TLS_VERIFY=true --- # Source: gitea/templates/gitea/config.yaml apiVersion: v1 kind: Secret metadata: name: my-gitea namespace: gitea labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm type: Opaque stringData: config_environment.sh: | #!/usr/bin/env bash set -euo pipefail function env2ini::log() { printf "${1}\n" } function env2ini::read_config_to_env() { local section="${1}" local line="${2}" if [[ -z "${line}" ]]; then # skip empty line return fi # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" if [[ -z "${setting}" ]]; then env2ini::log ' ! invalid setting' exit 1 fi local value='' local regex="^${setting}(\s*)=(\s*)(.*)" if [[ $line =~ $regex ]]; then value="${BASH_REMATCH[3]}" else env2ini::log ' ! invalid setting' exit 1 fi env2ini::log " + '${setting}'" if [[ -z "${section}" ]]; then export "GITEA____${setting^^}=${value}" # '^^' makes the variable content uppercase return fi local masked_section="${section//./_0X2E_}" # '//' instructs to replace all matches masked_section="${masked_section//-/_0X2D_}" export "GITEA__${masked_section^^}__${setting^^}=${value}" # '^^' makes the variable content uppercase } function env2ini::reload_preset_envs() { env2ini::log "Reloading preset envs..." while read -r line; do if [[ -z "${line}" ]]; then # skip empty line return fi # 'xargs echo -n' trims all leading/trailing whitespaces and a trailing new line local setting="$(awk -F '=' '{print $1}' <<< "${line}" | xargs echo -n)" if [[ -z "${setting}" ]]; then env2ini::log ' ! invalid setting' exit 1 fi local value='' local regex="^${setting}(\s*)=(\s*)(.*)" if [[ $line =~ $regex ]]; then value="${BASH_REMATCH[3]}" else env2ini::log ' ! invalid setting' exit 1 fi env2ini::log " + '${setting}'" export "${setting^^}=${value}" # '^^' makes the variable content uppercase done < "$TMP_EXISTING_ENVS_FILE" rm $TMP_EXISTING_ENVS_FILE } function env2ini::process_config_file() { local config_file="${1}" local section="$(basename "${config_file}")" if [[ $section == '_generals_' ]]; then env2ini::log " [ini root]" section='' else env2ini::log " ${section}" fi while read -r line; do env2ini::read_config_to_env "${section}" "${line}" done < <(awk 1 "${config_file}") # Helm .toYaml trims the trailing new line which breaks line processing; awk 1 ... adds it back while reading } function env2ini::load_config_sources() { local path="${1}" if [[ -d "${path}" ]]; then env2ini::log "Processing $(basename "${path}")..." while read -d '' configFile; do env2ini::process_config_file "${configFile}" done < <(find "${path}" -type l -not -name '..data' -print0) env2ini::log "\n" fi } function env2ini::generate_initial_secrets() { # These environment variables will either be # - overwritten with user defined values, # - initially used to set up Gitea # Anyway, they won't harm existing app.ini files export GITEA__SECURITY__INTERNAL_TOKEN=$(gitea generate secret INTERNAL_TOKEN) export GITEA__SECURITY__SECRET_KEY=$(gitea generate secret SECRET_KEY) export GITEA__OAUTH2__JWT_SECRET=$(gitea generate secret JWT_SECRET) export GITEA__SERVER__LFS_JWT_SECRET=$(gitea generate secret LFS_JWT_SECRET) env2ini::log "...Initial secrets generated\n" } # save existing envs prior to script execution. Necessary to keep order of preexisting and custom envs env | (grep -e '^GITEA__' || [[ $? == 1 ]]) > $TMP_EXISTING_ENVS_FILE # MUST BE CALLED BEFORE OTHER CONFIGURATION env2ini::generate_initial_secrets env2ini::load_config_sources "$ENV_TO_INI_MOUNT_POINT/inlines/" env2ini::load_config_sources "$ENV_TO_INI_MOUNT_POINT/additionals/" # load existing envs to override auto generated envs env2ini::reload_preset_envs env2ini::log "=== All configuration sources loaded ===\n" # safety to prevent rewrite of secret keys if an app.ini already exists if [ -f ${GITEA_APP_INI} ]; then env2ini::log 'An app.ini file already exists. To prevent overwriting secret keys, these settings are dropped and remain unchanged:' env2ini::log ' - security.INTERNAL_TOKEN' env2ini::log ' - security.SECRET_KEY' env2ini::log ' - oauth2.JWT_SECRET' env2ini::log ' - server.LFS_JWT_SECRET' unset GITEA__SECURITY__INTERNAL_TOKEN unset GITEA__SECURITY__SECRET_KEY unset GITEA__OAUTH2__JWT_SECRET unset GITEA__SERVER__LFS_JWT_SECRET fi environment-to-ini -o $GITEA_APP_INI assertions: | --- # Source: gitea/templates/gitea/init.yaml apiVersion: v1 kind: Secret metadata: name: my-gitea-init namespace: gitea labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm type: Opaque stringData: configure_gpg_environment.sh: | #!/usr/bin/env bash set -eu gpg --batch --import "$TMP_RAW_GPG_KEY" init_directory_structure.sh: |- #!/usr/bin/env bash set -euo pipefail mkdir -pv /data/git/.ssh chmod -Rv 700 /data/git/.ssh [ ! -d /data/gitea/conf ] && mkdir -pv /data/gitea/conf # prepare temp directory structure mkdir -pv "${GITEA_TEMP}" chmod -v ug+rwx "${GITEA_TEMP}" configure_gitea.sh: |- #!/usr/bin/env bash set -euo pipefail echo '==== BEGIN GITEA CONFIGURATION ====' { # try gitea migrate } || { # catch echo "Gitea migrate might fail due to database connection...This init-container will try again in a few seconds" exit 1 } function configure_admin_user() { local full_admin_list=$(gitea admin user list --admin) local actual_user_table='' # We might have distorted output due to warning logs, so we have to detect the actual user table by its headline and trim output above that line local regex="(.*)(ID\s+Username\s+Email\s+IsActive.*)" if [[ "${full_admin_list}" =~ $regex ]]; then actual_user_table=$(echo "${BASH_REMATCH[2]}" | tail -n+2) # tail'ing to drop the table headline else # This code block should never be reached, as long as the output table header remains the same. # If this code block is reached, the regex doesn't match anymore and we probably have to adjust this script. echo "ERROR: 'configure_admin_user' was not able to determine the current list of admin users." echo " Please review the output of 'gitea admin user list --admin' shown below." echo " If you think it is an issue with the Helm Chart provisioning, file an issue at https://gitea.com/gitea/helm-gitea/issues." echo "DEBUG: Output of 'gitea admin user list --admin'" echo "--" echo "${full_admin_list}" echo "--" exit 1 fi local ACCOUNT_ID=$(echo "${actual_user_table}" | grep -E "\s+${GITEA_ADMIN_USERNAME}\s+" | awk -F " " "{printf \$1}") if [[ -z "${ACCOUNT_ID}" ]]; then local -a create_args create_args=(--admin --username "${GITEA_ADMIN_USERNAME}" --password "${GITEA_ADMIN_PASSWORD}" --email "gitea@local.domain") if [[ "${GITEA_ADMIN_PASSWORD_MODE}" = initialOnlyRequireReset ]]; then create_args+=(--must-change-password=true) else create_args+=(--must-change-password=false) fi echo "No admin user '${GITEA_ADMIN_USERNAME}' found. Creating now..." gitea admin user create "${create_args[@]}" echo '...created.' else if [[ "${GITEA_ADMIN_PASSWORD_MODE}" = keepUpdated ]]; then echo "Admin account '${GITEA_ADMIN_USERNAME}' already exist. Running update to sync password..." # See https://gitea.com/gitea/helm-gitea/issues/673 # --must-change-password argument was added to change-password, defaulting to true, counter to the previous behavior # which acted as if it were provided with =false. If the argument is present in this version of gitea, then we # should add it to prevent requiring frequent admin password resets. local -a change_args change_args=(--username "${GITEA_ADMIN_USERNAME}" --password "${GITEA_ADMIN_PASSWORD}") if gitea admin user change-password --help | grep -qF -- '--must-change-password'; then change_args+=(--must-change-password=false) fi gitea admin user change-password "${change_args[@]}" echo '...password sync done.' else echo "Admin account '${GITEA_ADMIN_USERNAME}' already exist, but update mode is set to '${GITEA_ADMIN_PASSWORD_MODE}'. Skipping." fi fi } configure_admin_user function configure_ldap() { echo 'no ldap configuration... skipping.' } configure_ldap function configure_oauth() { echo 'no oauth configuration... skipping.' } configure_oauth echo '==== END GITEA CONFIGURATION ====' --- # Source: gitea/templates/gitea/pvc.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: gitea-shared-storage namespace: gitea annotations: helm.sh/resource-policy: keep labels: {} spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 5Gi --- # Source: gitea/templates/gitea/http-svc.yaml apiVersion: v1 kind: Service metadata: name: my-gitea-http namespace: gitea labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm annotations: {} spec: type: NodePort externalTrafficPolicy: Local ports: - name: http port: 3000 nodePort: 32223 targetPort: selector: app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea --- # Source: gitea/templates/gitea/ssh-svc.yaml apiVersion: v1 kind: Service metadata: name: my-gitea-ssh namespace: gitea labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm annotations: {} spec: type: NodePort externalTrafficPolicy: Local ports: - name: ssh port: 32222 targetPort: 2222 protocol: TCP nodePort: 32222 selector: app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea --- # Source: gitea/templates/gitea/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-gitea namespace: gitea annotations: labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm spec: replicas: 1 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 100% selector: matchLabels: app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea template: metadata: annotations: checksum/config: 529f6c0b7da42b761507752b5efbd94a13eec00379a39efd0b561b3901796044 labels: helm.sh/chart: gitea-12.1.2 app: gitea app.kubernetes.io/name: gitea app.kubernetes.io/instance: my-gitea app.kubernetes.io/version: "1.24.3" version: "1.24.3" app.kubernetes.io/managed-by: Helm spec: securityContext: fsGroup: 1000 initContainers: - name: init-directories image: "docker.gitea.com/gitea:1.24.3-rootless" imagePullPolicy: IfNotPresent command: - "/usr/sbinx/init_directory_structure.sh" env: - name: GITEA_APP_INI value: /data/gitea/conf/app.ini - name: GITEA_CUSTOM value: /data/gitea - name: GITEA_WORK_DIR value: /data - name: GITEA_TEMP value: /tmp/gitea volumeMounts: - name: init mountPath: /usr/sbinx - name: temp mountPath: /tmp - name: data mountPath: /data securityContext: {} resources: limits: {} requests: cpu: 100m memory: 128Mi - name: init-app-ini image: "docker.gitea.com/gitea:1.24.3-rootless" imagePullPolicy: IfNotPresent command: - "/usr/sbinx/config_environment.sh" env: - name: GITEA_APP_INI value: /data/gitea/conf/app.ini - name: GITEA_CUSTOM value: /data/gitea - name: GITEA_WORK_DIR value: /data - name: GITEA_TEMP value: /tmp/gitea - name: TMP_EXISTING_ENVS_FILE value: /tmp/existing-envs - name: ENV_TO_INI_MOUNT_POINT value: /env-to-ini-mounts volumeMounts: - name: config mountPath: /usr/sbinx - name: temp mountPath: /tmp - name: data mountPath: /data - name: inline-config-sources mountPath: /env-to-ini-mounts/inlines/ securityContext: {} resources: limits: {} requests: cpu: 100m memory: 128Mi - name: configure-gitea image: "docker.gitea.com/gitea:1.24.3-rootless" command: - "/usr/sbinx/configure_gitea.sh" imagePullPolicy: IfNotPresent securityContext: runAsUser: 1000 env: - name: GITEA_APP_INI value: /data/gitea/conf/app.ini - name: GITEA_CUSTOM value: /data/gitea - name: GITEA_WORK_DIR value: /data - name: GITEA_TEMP value: /tmp/gitea - name: HOME value: /data/gitea/git - name: GITEA_ADMIN_USERNAME valueFrom: secretKeyRef: key: username name: gitea-credential - name: GITEA_ADMIN_PASSWORD valueFrom: secretKeyRef: key: password name: gitea-credential - name: GITEA_ADMIN_PASSWORD_MODE value: keepUpdated volumeMounts: - name: init mountPath: /usr/sbinx - name: temp mountPath: /tmp - name: data mountPath: /data resources: limits: {} requests: cpu: 100m memory: 128Mi terminationGracePeriodSeconds: 60 containers: - name: gitea image: "docker.gitea.com/gitea:1.24.3-rootless" imagePullPolicy: IfNotPresent env: # SSH Port values have to be set here as well for openssh configuration - name: SSH_LISTEN_PORT value: "2222" - name: SSH_PORT value: "32222" - name: GITEA_APP_INI value: /data/gitea/conf/app.ini - name: GITEA_CUSTOM value: /data/gitea - name: GITEA_WORK_DIR value: /data - name: GITEA_TEMP value: /tmp/gitea - name: TMPDIR value: /tmp/gitea - name: HOME value: /data/gitea/git ports: - name: ssh containerPort: 2222 - name: http containerPort: 3000 livenessProbe: failureThreshold: 10 initialDelaySeconds: 200 periodSeconds: 10 successThreshold: 1 tcpSocket: port: http timeoutSeconds: 1 readinessProbe: failureThreshold: 3 initialDelaySeconds: 5 periodSeconds: 10 successThreshold: 1 tcpSocket: port: http timeoutSeconds: 1 resources: {} securityContext: {} volumeMounts: - name: temp mountPath: /tmp - name: data mountPath: /data volumes: - name: init secret: secretName: my-gitea-init defaultMode: 110 - name: config secret: secretName: my-gitea defaultMode: 110 - name: inline-config-sources secret: secretName: my-gitea-inline-config - name: temp emptyDir: {} - name: data persistentVolumeClaim: claimName: gitea-shared-storage {{- if .UsePathRouting }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path-oci-root namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2 pathType: Prefix {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2 pathType: Prefix {{ end }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path-oci-repo namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /v2/$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2/gitea(/|$)(.*) pathType: ImplementationSpecific {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /v2/gitea(/|$)(.*) pathType: ImplementationSpecific {{ end }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-path namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - host: {{ .IngressHost }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /gitea(/|$)(.*) pathType: ImplementationSpecific {{- if ne .IngressHost .Host }} - host: {{ .Host }} http: paths: - backend: service: name: my-gitea-http port: number: 3000 path: /gitea(/|$)(.*) pathType: ImplementationSpecific {{ end }} {{ else }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gitea-custom namespace: gitea annotations: nginx.ingress.kubernetes.io/proxy-body-size: 1024m spec: ingressClassName: nginx rules: - host: gitea.{{ .IngressHost }} http: paths: - path: / pathType: Prefix backend: service: name: my-gitea-http port: number: 3000 {{- if ne .IngressHost .Host }} - host: gitea.{{ .Host }} http: paths: - path: / pathType: Prefix backend: service: name: my-gitea-http port: number: 3000 {{ end }} {{ end }} ================================================ FILE: pkg/controllers/localbuild/resources/nginx/k8s/ingress-nginx.yaml ================================================ # INGRESS-NGINX INSTALL RESOURCES # This file is auto-generated with 'hack/ingress-nginx/generate-manifests.sh' apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - "" resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - coordination.k8s.io resourceNames: - ingress-nginx-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - "" resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: allow-snippet-annotations: "true" proxy-buffer-size: 32k proxy-busy-buffers-size: 32k use-forwarded-headers: "true" kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 spec: automountServiceAccountToken: true containers: - args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key - --watch-ingress-without-class=true - --publish-status-address=localhost - --enable-ssl-passthrough - --default-ssl-certificate=ingress-nginx/idpbuilder-cert env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.k8s.io/ingress-nginx/controller:v1.13.0@sha256:dc75a7baec7a3b827a5d7ab0acd10ab507904c7dad692365b3e3b596eca1afd2 imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 hostPort: 80 name: http protocol: TCP - containerPort: 443 hostPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: false capabilities: add: - NET_BIND_SERVICE drop: - ALL readOnlyRootFilesystem: false runAsGroup: 82 runAsNonRoot: true runAsUser: 101 seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 0 tolerations: - effect: NoSchedule key: node-role.kubernetes.io/master operator: Equal - effect: NoSchedule key: node-role.kubernetes.io/control-plane operator: Equal volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission-create spec: automountServiceAccountToken: true containers: - args: - create - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace=$(POD_NAMESPACE) - --secret-name=ingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.0@sha256:c9f76a75fd00e975416ea1b73300efd413116de0de8570346ed90766c5b5cefb imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure serviceAccountName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission-patch spec: automountServiceAccountToken: true containers: - args: - patch - --webhook-name=ingress-nginx-admission - --namespace=$(POD_NAMESPACE) - --patch-mutating=false - --secret-name=ingress-nginx-admission - --patch-failure-policy=Fail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.0@sha256:c9f76a75fd00e975416ea1b73300efd413116de0de8570346ed90766c5b5cefb imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure serviceAccountName: ingress-nginx-admission --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.0 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses port: 443 failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: {{ .Protocol }} name: {{ .Protocol }}-{{ .Port }} port: {{ .Port }} protocol: TCP targetPort: {{ .Protocol }} - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort ================================================ FILE: pkg/controllers/resources/idpbuilder.cnoe.io_custompackages.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.20.0 name: custompackages.idpbuilder.cnoe.io spec: group: idpbuilder.cnoe.io names: kind: CustomPackage listKind: CustomPackageList plural: custompackages singular: custompackage scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: CustomPackageSpec controls the installation of the custom applications. properties: argoCD: properties: applicationFile: description: ApplicationFile specifies the absolute path to the ArgoCD application file type: string name: type: string namespace: type: string type: enum: - Application - ApplicationSet type: string required: - applicationFile - name - namespace - type type: object gitServerAuthSecretRef: properties: name: type: string namespace: type: string required: - name - namespace type: object gitServerURL: description: |- GitServerURL specifies the base URL for the git server for API calls. for example, https://gitea.cnoe.localtest.me:8443 type: string internalGitServeURL: description: |- InternalGitServeURL specifies the base URL for the git server accessible within the cluster. for example, http://my-gitea-http.gitea.svc.cluster.local:3000 type: string remoteRepository: description: RemoteRepositorySpec specifies information about remote repositories. properties: cloneSubmodules: type: boolean path: type: string ref: description: Ref specifies the specific ref supported by git fetch type: string url: description: Url specifies the url to the repository containing the ArgoCD application file type: string required: - cloneSubmodules - path - ref - url type: object replicate: default: false description: Replicate specifies whether to replicate remote or local contents to the local gitea server. type: boolean required: - gitServerAuthSecretRef - gitServerURL - internalGitServeURL - remoteRepository - replicate type: object status: properties: gitRepositoryRefs: items: properties: apiVersion: type: string kind: type: string name: type: string namespace: type: string uid: type: string type: object type: array synced: description: |- A Custom package is considered synced when the in-cluster repository url is set as the repository URL This only applies for a package that references local directories type: boolean type: object type: object served: true storage: true subresources: status: {} ================================================ FILE: pkg/controllers/resources/idpbuilder.cnoe.io_gitrepositories.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.20.0 name: gitrepositories.idpbuilder.cnoe.io spec: group: idpbuilder.cnoe.io names: kind: GitRepository listKind: GitRepositoryList plural: gitrepositories singular: gitrepository scope: Namespaced versions: - name: v1alpha1 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: customization: description: PackageCustomization defines how packages are customized properties: filePath: description: FilePath is the absolute file path to a YAML file that contains Kubernetes manifests. type: string name: description: Name is the name of the package to be customized. e.g. argocd type: string required: - name type: object provider: properties: gitURL: description: GitURL is the base URL of Git server used for API calls. pattern: ^https?:\/\/.+$ type: string internalGitURL: description: InternalGitURL is the base URL of Git server accessible within the cluster only. type: string name: enum: - gitea - github type: string organizationName: type: string required: - gitURL - internalGitURL - name - organizationName type: object secretRef: description: SecretRef is the reference to secret that contain Git server credentials properties: name: type: string namespace: type: string required: - name - namespace type: object source: properties: embeddedAppName: enum: - argocd - gitea - nginx type: string path: description: |- Path is the absolute path to directory that contains Kustomize structure or raw manifests. This is required when Type is set to local. type: string remoteRepository: description: RemoteRepositorySpec specifies information about remote repositories. properties: cloneSubmodules: type: boolean path: type: string ref: description: Ref specifies the specific ref supported by git fetch type: string url: description: Url specifies the url to the repository containing the ArgoCD application file type: string required: - cloneSubmodules - path - ref - url type: object type: default: embedded description: Type is the source type. enum: - local - embedded - remote type: string required: - remoteRepository - type type: object required: - provider type: object status: properties: commit: description: LatestCommit is the most recent commit known to the controller properties: hash: description: Hash is the digest of the most recent commit type: string type: object externalGitRepositoryUrl: description: ExternalGitRepositoryUrl is the url for the in-cluster repository accessible from local machine. type: string internalGitRepositoryUrl: description: InternalGitRepositoryUrl is the url for the in-cluster repository accessible within the cluster. type: string path: description: Path is the path within the repository that contains the files. type: string synced: type: boolean required: - synced type: object type: object served: true storage: true subresources: status: {} ================================================ FILE: pkg/controllers/resources/idpbuilder.cnoe.io_localbuilds.yaml ================================================ --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.20.0 name: localbuilds.idpbuilder.cnoe.io spec: group: idpbuilder.cnoe.io names: kind: Localbuild listKind: LocalbuildList plural: localbuilds singular: localbuild scope: Cluster versions: - name: v1alpha1 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: buildCustomization: description: BuildCustomizationSpec fields cannot change once a cluster is created properties: host: type: string ingressHost: type: string insecureRegistryMirrors: type: boolean port: type: string protocol: type: string registryMirrors: items: description: RegistryMirror defines an external registry mirror configuration properties: registryAddress: description: RegistryAddress is the address of the mirror registry (e.g., "http://kind-registry:5000") type: string targetRegistry: description: TargetRegistry is the registry that should be mirrored (e.g., "docker.io", "ghcr.io") type: string type: object type: array selfSignedCert: type: string staticPassword: type: boolean usePathRouting: type: boolean type: object packageConfigs: properties: argoPackageConfigs: description: |- ArgoPackageConfigSpec Allows for configuration of the ArgoCD Installation. If no fields are specified then the binary embedded resources will be used to install ArgoCD. properties: enabled: description: Enabled controls whether to install ArgoCD. type: boolean type: object customPackageDirs: items: type: string type: array customPackageFiles: items: type: string type: array customPackageUrls: items: type: string type: array embeddedArgoApplicationsPackageConfigs: description: EmbeddedArgoApplicationsPackageConfigSpec Controls the installation of the embedded argo applications. properties: enabled: description: Enabled controls whether to install the embedded argo applications and the associated GitServer type: boolean type: object packageCustomization: additionalProperties: description: PackageCustomization defines how packages are customized properties: filePath: description: FilePath is the absolute file path to a YAML file that contains Kubernetes manifests. type: string name: description: Name is the name of the package to be customized. e.g. argocd type: string required: - name type: object type: object type: object type: object status: properties: ArgoCD: properties: appsCreated: type: boolean available: type: boolean type: object gitea: properties: adminUserSecretNameecret: type: string adminUserSecretNamespace: type: string available: type: boolean externalURL: type: string internalURL: type: string type: object nginx: properties: available: type: boolean type: object observedGeneration: description: ObservedGeneration is the 'Generation' of the Service that was last processed by the controller. format: int64 type: integer type: object type: object served: true storage: true subresources: status: {} ================================================ FILE: pkg/controllers/run.go ================================================ package controllers import ( "context" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/controllers/custompackage" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/cnoe-io/idpbuilder/pkg/controllers/gitrepository" "github.com/cnoe-io/idpbuilder/pkg/controllers/localbuild" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" ) func RunControllers( ctx context.Context, mgr manager.Manager, exitCh chan error, ctxCancel context.CancelFunc, exitOnSync bool, cfg v1alpha1.BuildCustomizationSpec, tmpDir string, ) error { logger := log.FromContext(ctx) repoMap := util.NewRepoLock() // Run Localbuild controller if err := (&localbuild.LocalbuildReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), ExitOnSync: exitOnSync, CancelFunc: ctxCancel, Config: cfg, TempDir: tmpDir, RepoMap: repoMap, }).SetupWithManager(mgr); err != nil { logger.Error(err, "unable to create localbuild controller") return err } err := (&gitrepository.RepositoryReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("gitrepository-controller"), Config: cfg, GitProviderFunc: gitrepository.GetGitProvider, TempDir: tmpDir, RepoMap: repoMap, }).SetupWithManager(mgr, nil) if err != nil { logger.Error(err, "unable to create repo controller") } err = (&custompackage.Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Recorder: mgr.GetEventRecorderFor("custompackage-controller"), TempDir: tmpDir, RepoMap: repoMap, }).SetupWithManager(mgr) if err != nil { logger.Error(err, "unable to create custom package controller") } // Start our manager in another goroutine logger.V(1).Info("starting manager") go func() { exitCh <- mgr.Start(ctx) close(exitCh) }() return nil } ================================================ FILE: pkg/k8s/client.go ================================================ package k8s import ( "context" "fmt" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) func EnsureObject(ctx context.Context, kubeClient client.Client, obj client.Object, namespace string) error { curObj := &unstructured.Unstructured{} curObj.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind()) // Fallback to object's namespace if namespace == "" { namespace = obj.GetNamespace() } // Get Object if it exists err := kubeClient.Get( ctx, types.NamespacedName{ Namespace: namespace, Name: obj.GetName(), }, curObj, ) if err == nil { // Object already exists return nil } err = kubeClient.Create(ctx, obj) if err != nil { return err } // hacky way to restore the GVK for the object after create corrupts it. didn't dig. not sure why? obj.GetObjectKind().SetGroupVersionKind(curObj.GroupVersionKind()) return nil } func EnsureNamespace(ctx context.Context, kubeClient client.Client, name string) error { ns := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, } err := kubeClient.Get(ctx, client.ObjectKeyFromObject(ns), ns) if err != nil { if k8serrors.IsNotFound(err) { return kubeClient.Create(ctx, ns) } else { return fmt.Errorf("getting namespace %s: %w", name, err) } } return nil } ================================================ FILE: pkg/k8s/deserialize.go ================================================ package k8s import ( "bytes" "fmt" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kustomize/kyaml/kio" kyaml "sigs.k8s.io/kustomize/kyaml/yaml" ) type ConversionError struct { rtObject runtime.Object } func (e *ConversionError) Error() string { return fmt.Sprintf("Failed to convert object %q", e.rtObject.GetObjectKind().GroupVersionKind().String()) } func ConvertYamlToObjects(scheme *runtime.Scheme, objYamls []byte) ([]client.Object, error) { decode := serializer.NewCodecFactory(scheme).UniversalDeserializer().Decode var k8sObjects []client.Object for _, objYaml := range bytes.Split(objYamls, []byte{'\n', '-', '-', '-', '\n'}) { if len(objYaml) == 0 { continue } rtObject, _, err := decode(objYaml, nil, nil) if err != nil { return nil, err } object, ok := rtObject.(client.Object) if !ok { return nil, &ConversionError{rtObject: rtObject} } k8sObjects = append(k8sObjects, object) } return k8sObjects, nil } func ConvertRawResourcesToObjects(scheme *runtime.Scheme, rawResources [][]byte) ([]client.Object, error) { var ret []client.Object for _, resources := range rawResources { objs, err := ConvertYamlToObjects(scheme, resources) if err != nil { return nil, err } ret = append(ret, objs...) } return ret, nil } // replace k8s objects in given YAML doc with override objects. returns built yaml file and objects func ConvertYamlToObjectsWithOverride(scheme *runtime.Scheme, originalFiles [][]byte, overrideYamls []byte) ([][]byte, []client.Object, error) { overrides, err := kio.FromBytes(overrideYamls) if err != nil { return nil, nil, err } overrideMap := make(map[string]*kyaml.RNode) order := make([]string, 0, len(overrides)) for i := range overrides { o := overrides[i] id := GetObjectIdentifier(o) overrideMap[id] = o order = append(order, id) } outYaml := make([][]byte, len(originalFiles)) outObjs := make([]client.Object, 0, 10) for i := range originalFiles { originalFile := originalFiles[i] originals, oErr := kio.FromBytes(originalFile) if oErr != nil { return nil, nil, oErr } for j := range originals { id := GetObjectIdentifier(originals[j]) o, ok := overrideMap[id] if ok { // found an object that needs to be overridden. update manifest and remove from our map. originals[j].SetYNode(o.YNode()) delete(overrideMap, id) } } manifest, oErr := kio.StringAll(originals) if oErr != nil { return nil, nil, fmt.Errorf("converting overridden manifest to string: %w", oErr) } objs, oErr := ConvertYamlToObjects(scheme, []byte(manifest)) if oErr != nil { return nil, nil, fmt.Errorf("converting overridden manifest to k8s objects: %w", oErr) } outObjs = append(outObjs, objs...) outYaml[i] = []byte(manifest) } // if there are objects that are not overriding any original object, create a new file and add them to it. if len(overrideMap) != 0 { // must preserve original order n := make([]*kyaml.RNode, 0, len(overrideYamls)) for i := range order { o, ok := overrideMap[order[i]] if ok { n = append(n, o) } } manifest, err := kio.StringAll(n) if err != nil { return nil, nil, fmt.Errorf("converting overridden manifest to string: %w", err) } objs, oErr := ConvertYamlToObjects(scheme, []byte(manifest)) if oErr != nil { return nil, nil, fmt.Errorf("converting overridden manifest to k8s objects: %w", oErr) } outObjs = append(outObjs, objs...) outYaml = append(outYaml, []byte(manifest)) } return outYaml, outObjs, nil } func GetObjectIdentifier(n *kyaml.RNode) string { return fmt.Sprintf("%s%s%s%s", n.GetApiVersion(), n.GetKind(), n.GetNamespace(), n.GetName()) } ================================================ FILE: pkg/k8s/deserialize_test.go ================================================ package k8s import ( "testing" "github.com/google/go-cmp/cmp" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) func newDeployment(name string) *appsv1.Deployment { return &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.Identifier(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, }, } } func TestConvertYamlToObjects(t *testing.T) { cases := []struct { name string schemeBuilder runtime.SchemeBuilder input string expectErr error expectObjects []client.Object }{{ name: "Single Deployment", schemeBuilder: appsv1.SchemeBuilder, input: ` apiVersion: apps/v1 kind: Deployment metadata: name: test-deployment1 spec:`, expectErr: nil, expectObjects: []client.Object{ newDeployment("test-deployment1"), }, }, { name: "Multi Deployment", schemeBuilder: appsv1.SchemeBuilder, input: ` apiVersion: apps/v1 kind: Deployment metadata: name: test-deployment1 spec: --- apiVersion: apps/v1 kind: Deployment metadata: name: test-deployment2 spec:`, expectErr: nil, expectObjects: []client.Object{ newDeployment("test-deployment1"), newDeployment("test-deployment2"), }, }} for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { scheme := runtime.NewScheme() tc.schemeBuilder.AddToScheme(scheme) objs, err := ConvertYamlToObjects(scheme, []byte(tc.input)) if err != tc.expectErr { t.Fatalf("want err: %v, got err %v", tc.expectErr, err) } if diff := cmp.Diff(tc.expectObjects, objs); diff != "" { t.Errorf("ConvertYamlToObjects() mismatch (-want +got):\n%s", diff) } }) } } ================================================ FILE: pkg/k8s/schema.go ================================================ package k8s import ( argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) func GetScheme() *runtime.Scheme { scheme := runtime.NewScheme() schemeBuilder := runtime.NewSchemeBuilder( admissionregistrationv1.AddToScheme, apiextensionsv1.AddToScheme, appsv1.AddToScheme, batchv1.AddToScheme, corev1.AddToScheme, networkingv1.AddToScheme, rbacv1.AddToScheme, argov1alpha1.AddToScheme, v1alpha1.AddToScheme, ) schemeBuilder.AddToScheme(scheme) return scheme } ================================================ FILE: pkg/k8s/test-resources/input/argocd/install.yaml ================================================ # UCP ARGO INSTALL RESOURCES # This file is auto-generated with 'hack/argo-cd/generate-manifests.sh' apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applications.argoproj.io app.kubernetes.io/part-of: argocd name: applications.argoproj.io spec: group: argoproj.io names: kind: Application listKind: ApplicationList plural: applications shortNames: - app - apps singular: application scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .status.sync.status name: Sync Status type: string - jsonPath: .status.health.status name: Health Status type: string - jsonPath: .status.sync.revision name: Revision priority: 10 type: string name: v1alpha1 schema: openAPIV3Schema: description: Application is a definition of Application resource. 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 operation: description: Operation contains information about a requested or running operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object spec: description: ApplicationSpec represents desired application state. Contains link to repository with application definition and additional parameters link definition revision. properties: destination: description: Destination is a reference to the target Kubernetes server and namespace properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object ignoreDifferences: description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: description: Info contains a list of information (URLs, email addresses, and plain text) that relates to the application items: properties: name: type: string value: type: string required: - name - value type: object type: array project: description: Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project. type: string revisionHistoryLimit: description: RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions. This should only be changed in exceptional circumstances. Setting to zero will store no history. This will reduce storage used. Increasing will increase the space used to store the history, so we do not recommend increasing it. Default is 10. format: int64 type: integer source: description: Source is a reference to the location of the application's manifests or chart properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the location of the application's manifests or chart items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncPolicy: description: SyncPolicy controls when and how a sync will be performed properties: automated: description: Automated will keep an application synced to the target revision properties: allowEmpty: description: 'AllowEmpty allows apps have zero live resources (default: false)' type: boolean prune: description: 'Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false)' type: boolean selfHeal: description: 'SelfHeal specifies whether to revert resources back to their desired state upon modification in the cluster (default: false)' type: boolean type: object managedNamespaceMetadata: description: ManagedNamespaceMetadata controls metadata in the given namespace (if CreateNamespace=true) properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: description: Retry controls failed sync retry behavior properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object syncOptions: description: Options allow you to specify whole app sync-options items: type: string type: array type: object required: - destination - project type: object status: description: ApplicationStatus contains status information for the application properties: conditions: description: Conditions is a list of currently observed application conditions items: description: ApplicationCondition contains details about an application condition, which is usually an error or warning properties: lastTransitionTime: description: LastTransitionTime is the time the condition was last observed format: date-time type: string message: description: Message contains human-readable message indicating details about condition type: string type: description: Type is an application condition type type: string required: - message - type type: object type: array controllerNamespace: description: ControllerNamespace indicates the namespace in which the application controller is located type: string health: description: Health contains information about the application's current health status properties: message: description: Message is a human-readable informational message describing the health status type: string status: description: Status holds the status code of the application or resource type: string type: object history: description: History contains information about the application's sync history items: description: RevisionHistory contains history information about a previous sync properties: deployStartedAt: description: DeployStartedAt holds the time the sync operation started format: date-time type: string deployedAt: description: DeployedAt holds the time the sync operation completed format: date-time type: string id: description: ID is an auto incrementing identifier of the RevisionHistory format: int64 type: integer revision: description: Revision holds the revision the sync was performed against type: string revisions: description: Revisions holds the revision of each source in sources field the sync was performed against items: type: string type: array source: description: Source is a reference to the application source used for the sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application sources used for the sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - deployedAt - id type: object type: array observedAt: description: 'ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field' format: date-time type: string operationState: description: OperationState contains information about any ongoing operations, such as a sync properties: finishedAt: description: FinishedAt contains time of operation completion format: date-time type: string message: description: Message holds any pertinent messages when attempting to perform operation (typically errors). type: string operation: description: Operation is the original requested operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object phase: description: Phase is the current phase of the operation type: string retryCount: description: RetryCount contains time of operation retries format: int64 type: integer startedAt: description: StartedAt contains time of operation start format: date-time type: string syncResult: description: SyncResult is the result of a Sync operation properties: managedNamespaceMetadata: description: ManagedNamespaceMetadata contains the current sync state of managed namespace metadata properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object resources: description: Resources contains a list of sync result items for each individual resource in a sync operation items: description: ResourceResult holds the operation result details of a specific resource properties: group: description: Group specifies the API group of the resource type: string hookPhase: description: HookPhase contains the state of any operation associated with this resource OR hook This can also contain values for non-hook resources. type: string hookType: description: HookType specifies the type of the hook. Empty for non-hook resources type: string kind: description: Kind specifies the API kind of the resource type: string message: description: Message contains an informational or error message for the last sync OR operation type: string name: description: Name specifies the name of the resource type: string namespace: description: Namespace specifies the target namespace of the resource type: string status: description: Status holds the final result of the sync. Will be empty if the resources is yet to be applied/pruned and is always zero-value for hooks type: string syncPhase: description: SyncPhase indicates the particular phase of the sync that this result was acquired in type: string version: description: Version specifies the API version of the resource type: string required: - group - kind - name - namespace - version type: object type: array revision: description: Revision holds the revision this sync operation was performed to type: string revisions: description: Revisions holds the revision this sync operation was performed for respective indexed source in sources field items: type: string type: array source: description: Source records the application source information of the sync, used for comparing auto-sync properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Source records the application source information of the sync, used for comparing auto-sync items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - revision type: object required: - operation - phase - startedAt type: object reconciledAt: description: ReconciledAt indicates when the application state was reconciled using the latest git version format: date-time type: string resourceHealthSource: description: 'ResourceHealthSource indicates where the resource health status is stored: inline if not set or appTree' type: string resources: description: Resources is a list of Kubernetes resources managed by this application items: description: 'ResourceStatus holds the current sync and health status of a resource TODO: describe members of this type' properties: group: type: string health: description: HealthStatus contains information about the currently observed health state of an application or resource properties: message: description: Message is a human-readable informational message describing the health status type: string status: description: Status holds the status code of the application or resource type: string type: object hook: type: boolean kind: type: string name: type: string namespace: type: string requiresPruning: type: boolean status: description: SyncStatusCode is a type which represents possible comparison results type: string syncWave: format: int64 type: integer version: type: string type: object type: array sourceType: description: SourceType specifies the type of this application type: string sourceTypes: description: SourceTypes specifies the type of the sources included in the application items: description: ApplicationSourceType specifies the type of the application's source type: string type: array summary: description: Summary contains a list of URLs and container images used by this application properties: externalURLs: description: ExternalURLs holds all external URLs of application child resources. items: type: string type: array images: description: Images holds all images of application child resources. items: type: string type: array type: object sync: description: Sync contains information about the application's current sync status properties: comparedTo: description: ComparedTo contains information about what has been compared properties: destination: description: Destination is a reference to the application's destination used for comparison properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object ignoreDifferences: description: IgnoreDifferences is a reference to the application's ignored differences used for comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array source: description: Source is a reference to the application's source used for comparison properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application's multiple sources used for comparison items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - destination type: object revision: description: Revision contains information about the revision the comparison has been performed to type: string revisions: description: Revisions contains information about the revisions of multiple sources the comparison has been performed to items: type: string type: array status: description: Status is the sync state of the comparison type: string required: - status type: object type: object required: - metadata - spec type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applicationsets.argoproj.io app.kubernetes.io/part-of: argocd name: applicationsets.argoproj.io spec: group: argoproj.io names: kind: ApplicationSet listKind: ApplicationSetList plural: applicationsets shortNames: - appset - appsets singular: applicationset scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: properties: apiVersion: type: string kind: type: string metadata: type: object spec: properties: applyNestedSelectors: type: boolean generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators type: object merge: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array mergeKeys: items: type: string type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators - mergeKeys type: object plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array goTemplate: type: boolean goTemplateOptions: items: type: string type: array preservedFields: properties: annotations: items: type: string type: array type: object strategy: properties: rollingSync: properties: steps: items: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array type: object type: array maxUpdate: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true type: object type: array type: object type: type: string type: object syncPolicy: properties: applicationsSync: enum: - create-only - create-update - create-delete - sync type: string preserveResourcesOnDeletion: type: boolean type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators - template type: object status: properties: applicationStatus: items: properties: application: type: string lastTransitionTime: format: date-time type: string message: type: string status: type: string step: type: string required: - application - message - status - step type: object type: array conditions: items: properties: lastTransitionTime: format: date-time type: string message: type: string reason: type: string status: type: string type: type: string required: - message - reason - status - type type: object type: array type: object required: - metadata - spec type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: appprojects.argoproj.io app.kubernetes.io/part-of: argocd name: appprojects.argoproj.io spec: group: argoproj.io names: kind: AppProject listKind: AppProjectList plural: appprojects shortNames: - appproj - appprojs singular: appproject scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: 'AppProject provides a logical grouping of applications, providing controls for: * where the apps may deploy to (cluster whitelist) * what may be deployed (repository whitelist, resource whitelist/blacklist) * who can access these applications (roles, OIDC group claims bindings) * and what they can do (RBAC policies) * automation access to these roles (JWT tokens)' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: AppProjectSpec is the specification of an AppProject properties: clusterResourceBlacklist: description: ClusterResourceBlacklist contains list of blacklisted cluster level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array clusterResourceWhitelist: description: ClusterResourceWhitelist contains list of whitelisted cluster level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array description: description: Description contains optional project description type: string destinations: description: Destinations contains list of destinations available for deployment items: description: ApplicationDestination holds information about the application's destination properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object type: array namespaceResourceBlacklist: description: NamespaceResourceBlacklist contains list of blacklisted namespace level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array namespaceResourceWhitelist: description: NamespaceResourceWhitelist contains list of whitelisted namespace level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array orphanedResources: description: OrphanedResources specifies if controller should monitor orphaned resources of apps in this project properties: ignore: description: Ignore contains a list of resources that are to be excluded from orphaned resources monitoring items: description: OrphanedResourceKey is a reference to a resource to be ignored from properties: group: type: string kind: type: string name: type: string type: object type: array warn: description: Warn indicates if warning condition should be created for apps which have orphaned resources type: boolean type: object permitOnlyProjectScopedClusters: description: PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped type: boolean roles: description: Roles are user defined RBAC roles associated with this project items: description: ProjectRole represents a role that has access to a project properties: description: description: Description is a description of the role type: string groups: description: Groups are a list of OIDC group claims bound to this role items: type: string type: array jwtTokens: description: JWTTokens are a list of generated JWT tokens bound to this role items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array name: description: Name is a name for this role type: string policies: description: Policies Stores a list of casbin formatted strings that define access policies for the role in the project items: type: string type: array required: - name type: object type: array signatureKeys: description: SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync items: description: SignatureKey is the specification of a key required to verify commit signatures with properties: keyID: description: The ID of the key in hexadecimal notation type: string required: - keyID type: object type: array sourceNamespaces: description: SourceNamespaces defines the namespaces application resources are allowed to be created in items: type: string type: array sourceRepos: description: SourceRepos contains list of repository URLs which can be used for deployment items: type: string type: array syncWindows: description: SyncWindows controls when syncs can be run for apps in this project items: description: SyncWindow contains the kind, time, duration and attributes that are used to assign the syncWindows to apps properties: applications: description: Applications contains a list of applications that the window will apply to items: type: string type: array clusters: description: Clusters contains a list of clusters that the window will apply to items: type: string type: array duration: description: Duration is the amount of time the sync window will be open type: string kind: description: Kind defines if the window allows or blocks syncs type: string manualSync: description: ManualSync enables manual syncs when they would otherwise be blocked type: boolean namespaces: description: Namespaces contains a list of namespaces that the window will apply to items: type: string type: array schedule: description: Schedule is the time the window will begin, specified in cron format type: string timeZone: description: TimeZone of the sync that will be applied to the schedule type: string type: object type: array type: object status: description: AppProjectStatus contains status information for AppProject CRs properties: jwtTokensByRole: additionalProperties: description: JWTTokens represents a list of JWT tokens properties: items: items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array type: object description: JWTTokensByRole contains a list of JWT tokens issued for a given role type: object type: object required: - metadata - spec type: object served: true storage: true --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - argoproj.io resources: - applications - appprojects verbs: - create - get - list - watch - update - patch - delete - apiGroups: - "" resources: - events verbs: - create - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller rules: - apiGroups: - argoproj.io resources: - applications - applicationsets - applicationsets/finalizers verbs: - create - delete - get - list - patch - update - watch - apiGroups: - argoproj.io resources: - appprojects verbs: - get - apiGroups: - argoproj.io resources: - applicationsets/status verbs: - get - patch - update - apiGroups: - "" resources: - events verbs: - create - get - list - patch - watch - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - apps - extensions resources: - deployments verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller rules: - apiGroups: - argoproj.io resources: - applications - appprojects verbs: - get - list - watch - update - patch - apiGroups: - "" resources: - configmaps - secrets verbs: - list - watch - apiGroups: - "" resourceNames: - argocd-notifications-cm resources: - configmaps verbs: - get - apiGroups: - "" resourceNames: - argocd-notifications-secret resources: - secrets verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - create - get - list - watch - update - patch - delete - apiGroups: - argoproj.io resources: - applications - appprojects - applicationsets verbs: - create - get - list - watch - update - delete - patch - apiGroups: - "" resources: - events verbs: - create - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - '*' resources: - '*' verbs: - '*' - nonResourceURLs: - '*' verbs: - '*' --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - '*' resources: - '*' verbs: - delete - get - patch - apiGroups: - "" resources: - events verbs: - list - apiGroups: - "" resources: - pods - pods/log verbs: - get - apiGroups: - argoproj.io resources: - applications verbs: - get - list - watch - apiGroups: - batch resources: - jobs verbs: - create - apiGroups: - argoproj.io resources: - workflows verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-applicationset-controller subjects: - kind: ServiceAccount name: argocd-applicationset-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-dex-server subjects: - kind: ServiceAccount name: argocd-dex-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-notifications-controller subjects: - kind: ServiceAccount name: argocd-notifications-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-server subjects: - kind: ServiceAccount name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller namespace: argocd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-server subjects: - kind: ServiceAccount name: argocd-server namespace: argocd --- apiVersion: v1 data: application.resourceTrackingMethod: annotation resource.exclusions: | - kinds: - ProviderConfigUsage apiGroups: - "*" kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd name: argocd-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cmd-params-cm app.kubernetes.io/part-of: argocd name: argocd-cmd-params-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-gpg-keys-cm app.kubernetes.io/part-of: argocd name: argocd-gpg-keys-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-rbac-cm app.kubernetes.io/part-of: argocd name: argocd-rbac-cm --- apiVersion: v1 data: ssh_known_hosts: | # This file was automatically generated by hack/update-ssh-known-hosts.sh. DO NOT EDIT [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl [ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE= bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M= github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-ssh-known-hosts-cm app.kubernetes.io/part-of: argocd name: argocd-ssh-known-hosts-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-tls-certs-cm app.kubernetes.io/part-of: argocd name: argocd-tls-certs-cm --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-secret type: Opaque --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/name: argocd-secret app.kubernetes.io/part-of: argocd name: argocd-secret type: Opaque --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: ports: - name: webhook port: 7000 protocol: TCP targetPort: webhook - name: metrics port: 8080 protocol: TCP targetPort: metrics selector: app.kubernetes.io/name: argocd-applicationset-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: ports: - name: http port: 5556 protocol: TCP targetPort: 5556 - name: grpc port: 5557 protocol: TCP targetPort: 5557 - name: metrics port: 5558 protocol: TCP targetPort: 5558 selector: app.kubernetes.io/name: argocd-dex-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: metrics app.kubernetes.io/name: argocd-metrics app.kubernetes.io/part-of: argocd name: argocd-metrics spec: ports: - name: metrics port: 8082 protocol: TCP targetPort: 8082 selector: app.kubernetes.io/name: argocd-application-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller-metrics app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-metrics spec: ports: - name: metrics port: 9001 protocol: TCP targetPort: 9001 selector: app.kubernetes.io/name: argocd-notifications-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: ports: - name: tcp-redis port: 6379 targetPort: 6379 selector: app.kubernetes.io/name: argocd-redis --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: ports: - name: server port: 8081 protocol: TCP targetPort: 8081 - name: metrics port: 8084 protocol: TCP targetPort: 8084 selector: app.kubernetes.io/name: argocd-repo-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: ports: - name: http port: 80 protocol: TCP targetPort: 8080 - name: https port: 443 protocol: TCP targetPort: 8080 selector: app.kubernetes.io/name: argocd-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server-metrics app.kubernetes.io/part-of: argocd name: argocd-server-metrics spec: ports: - name: metrics port: 8083 protocol: TCP targetPort: 8083 selector: app.kubernetes.io/name: argocd-server --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: selector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller template: metadata: labels: app.kubernetes.io/name: argocd-applicationset-controller spec: containers: - args: - /usr/local/bin/argocd-applicationset-controller env: - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_LEADER_ELECTION valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.leader.election name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_POLICY valueFrom: configMapKeyRef: key: applicationsetcontroller.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.policy.override name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DEBUG valueFrom: configMapKeyRef: key: applicationsetcontroller.debug name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: applicationsetcontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: applicationsetcontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DRY_RUN valueFrom: configMapKeyRef: key: applicationsetcontroller.dryrun name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.progressive.syncs name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_NEW_GIT_FILE_GLOBBING valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.new.git.file.globbing name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_RECONCILIATIONS valueFrom: configMapKeyRef: key: applicationsetcontroller.concurrent.reconciliations.max name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_NAMESPACES valueFrom: configMapKeyRef: key: applicationsetcontroller.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH valueFrom: configMapKeyRef: key: applicationsetcontroller.scm.root.ca.path name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.allowed.scm.providers name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: argocd-applicationset-controller ports: - containerPort: 7000 name: webhook - containerPort: 8080 name: metrics securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /tmp name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls serviceAccountName: argocd-applicationset-controller volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-dex-server template: metadata: labels: app.kubernetes.io/name: argocd-dex-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - command: - /shared/argocd-dex - rundex env: - name: ARGOCD_DEX_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: dexserver.disable.tls name: argocd-cmd-params-cm optional: true image: ghcr.io/dexidp/dex:v2.37.0 imagePullPolicy: Always name: dex ports: - containerPort: 5556 - containerPort: 5557 - containerPort: 5558 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig - mountPath: /tls name: argocd-dex-server-tls initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /shared/argocd-dex image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig serviceAccountName: argocd-dex-server volumes: - emptyDir: {} name: static-files - emptyDir: {} name: dexconfig - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: argocd-notifications-controller spec: containers: - args: - /usr/local/bin/argocd-notifications env: - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: notificationscontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: tcpSocket: port: 9001 name: argocd-notifications-controller securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true volumeMounts: - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: selector: matchLabels: app.kubernetes.io/name: argocd-redis template: metadata: labels: app.kubernetes.io/name: argocd-redis spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-redis topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - --save - "" - --appendonly - "no" image: redis:7.0.11-alpine imagePullPolicy: Always name: redis ports: - containerPort: 6379 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true securityContext: runAsNonRoot: true runAsUser: 999 seccompProfile: type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-repo-server template: metadata: labels: app.kubernetes.io/name: argocd-repo-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 automountServiceAccountToken: false containers: - args: - /usr/local/bin/argocd-repo-server env: - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_REPO_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: reposerver.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LOGLEVEL valueFrom: configMapKeyRef: key: reposerver.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: reposerver.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: reposerver.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_METRICS_ADDRESS valueFrom: configMapKeyRef: key: reposerver.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: reposerver.disable.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: reposerver.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.repo.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE valueFrom: configMapKeyRef: key: reposerver.max.combined.directory.manifests.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS valueFrom: configMapKeyRef: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: key: reposerver.allow.oob.symlinks name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_TAR_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.tar.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.disable.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: reposerver.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: HELM_CACHE_HOME value: /helm-working-dir - name: HELM_CONFIG_HOME value: /helm-working-dir - name: HELM_DATA_HOME value: /helm-working-dir image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: failureThreshold: 3 httpGet: path: /healthz?full=true port: 8084 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 name: argocd-repo-server ports: - containerPort: 8081 - containerPort: 8084 readinessProbe: httpGet: path: /healthz port: 8084 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls - mountPath: /tmp name: tmp - mountPath: /helm-working-dir name: helm-working-dir - mountPath: /home/argocd/cmp-server/plugins name: plugins initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /var/run/argocd/argocd-cmp-server image: quay.io/argoproj/argocd:v2.8.7 name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files serviceAccountName: argocd-repo-server volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - emptyDir: {} name: helm-working-dir - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - emptyDir: {} name: var-files - emptyDir: {} name: plugins --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-server template: metadata: labels: app.kubernetes.io/name: argocd-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-server - '{{if .UsePathRouting}}' - --insecure - --basehref - /argocd - '{{end}}' env: - name: ARGOCD_SERVER_INSECURE valueFrom: configMapKeyRef: key: server.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_BASEHREF valueFrom: configMapKeyRef: key: server.basehref name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ROOTPATH valueFrom: configMapKeyRef: key: server.rootpath name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: server.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOG_LEVEL valueFrom: configMapKeyRef: key: server.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER valueFrom: configMapKeyRef: key: server.dex.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DISABLE_AUTH valueFrom: configMapKeyRef: key: server.disable.auth name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_GZIP valueFrom: configMapKeyRef: key: server.enable.gzip name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: server.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_X_FRAME_OPTIONS valueFrom: configMapKeyRef: key: server.x.frame.options name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONTENT_SECURITY_POLICY valueFrom: configMapKeyRef: key: server.content.security.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.dex.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.dex.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: server.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: server.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: server.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONNECTION_STATUS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.connection.status.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OIDC_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.oidc.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOGIN_ATTEMPTS_EXPIRATION valueFrom: configMapKeyRef: key: server.login.attempts.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_STATIC_ASSETS valueFrom: configMapKeyRef: key: server.staticassets name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_MAX_COOKIE_NUMBER valueFrom: configMapKeyRef: key: server.http.cookie.maxnumber name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_METRICS_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_PROXY_EXTENSION valueFrom: configMapKeyRef: key: server.enable.proxy.extension name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: httpGet: path: /healthz?full=true port: 8080 initialDelaySeconds: 3 periodSeconds: 30 timeoutSeconds: 5 name: argocd-server ports: - containerPort: 8080 - containerPort: 8083 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 3 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/server/tls name: argocd-repo-server-tls - mountPath: /app/config/dex/tls name: argocd-dex-server-tls - mountPath: /home/argocd name: plugins-home - mountPath: /tmp name: tmp serviceAccountName: argocd-server volumes: - emptyDir: {} name: plugins-home - emptyDir: {} name: tmp - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: argocd-application-controller serviceName: argocd-application-controller template: metadata: labels: app.kubernetes.io/name: argocd-application-controller spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-application-controller env: - name: ARGOCD_CONTROLLER_REPLICAS value: "1" - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_HARD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.hard.reconciliation name: argocd-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_STATUS_PROCESSORS valueFrom: configMapKeyRef: key: controller.status.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OPERATION_PROCESSORS valueFrom: configMapKeyRef: key: controller.operation.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: controller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: controller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.metrics.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: controller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: controller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_PERSIST_RESOURCE_HEALTH valueFrom: configMapKeyRef: key: controller.resource.health.persist name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_CONTROLLER_SHARDING_ALGORITHM valueFrom: configMapKeyRef: key: controller.sharding.algorithm name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_KUBECTL_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: controller.kubectl.parallelism.limit name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: argocd-application-controller ports: - containerPort: 8082 readinessProbe: httpGet: path: /healthz port: 8082 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls - mountPath: /home/argocd name: argocd-home workingDir: /home/argocd serviceAccountName: argocd-application-controller volumes: - emptyDir: {} name: argocd-home - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-application-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 8082 podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-applicationset-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 7000 protocol: TCP - port: 8080 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-dex-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server ports: - port: 5556 protocol: TCP - port: 5557 protocol: TCP - from: - namespaceSelector: {} ports: - port: 5558 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-dex-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 9001 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-redis-network-policy spec: egress: - ports: - port: 53 protocol: UDP - port: 53 protocol: TCP ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller ports: - port: 6379 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-redis policyTypes: - Ingress - Egress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-repo-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller ports: - port: 8081 protocol: TCP - from: - namespaceSelector: {} ports: - port: 8084 podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-server-network-policy spec: ingress: - {} podSelector: matchLabels: app.kubernetes.io/name: argocd-server policyTypes: - Ingress ================================================ FILE: pkg/k8s/test-resources/input/argocd-cm.yaml ================================================ apiVersion: v1 data: application.resourceTrackingMethod: annotation resource.exclusions: | - kinds: - ProviderConfigUsage apiGroups: - "*" kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd Test: Data name: argocd-cm ================================================ FILE: pkg/k8s/test-resources/input/extra.yaml ================================================ apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-one --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-two --- apiVersion: v1 kind: Service metadata: labels: test: test name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP ================================================ FILE: pkg/k8s/test-resources/input/extra.yaml.tmpl ================================================ apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-one --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-two --- apiVersion: v1 kind: Service metadata: labels: test: data name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: {{ .Protocol }} name: {{ .Protocol }}-{{ .Port }} port: {{ .Port }} protocol: TCP targetPort: {{ .Protocol }} - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort ================================================ FILE: pkg/k8s/test-resources/input/nginx/install.yaml ================================================ apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - "" resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - coordination.k8s.io resourceNames: - ingress-nginx-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - "" resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: allow-snippet-annotations: "true" proxy-buffer-size: 32k use-forwarded-headers: "true" kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 spec: containers: - args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key - --watch-ingress-without-class=true - --publish-status-address=localhost - --enable-ssl-passthrough env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.k8s.io/ingress-nginx/controller:v1.8.1@sha256:e5c4824e7375fcf2a393e1c03c293b69759af37a9ca6abdb91b13d78a93da8bd imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 hostPort: 80 name: http protocol: TCP - containerPort: 443 hostPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: true capabilities: add: - NET_BIND_SERVICE drop: - ALL runAsUser: 101 volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 0 volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create spec: containers: - args: - create - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace=$(POD_NAMESPACE) - --secret-name=ingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch spec: containers: - args: - patch - --webhook-name=ingress-nginx-admission - --namespace=$(POD_NAMESPACE) - --patch-mutating=false - --secret-name=ingress-nginx-admission - --patch-failure-policy=Fail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: {{ .Protocol }} name: {{ .Protocol }}-{{ .Port }} port: {{ .Port }} protocol: TCP targetPort: {{ .Protocol }} - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort ================================================ FILE: pkg/k8s/test-resources/output/argocd/install.yaml ================================================ # UCP ARGO INSTALL RESOURCES # This file is auto-generated with 'hack/argo-cd/generate-manifests.sh' apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applications.argoproj.io app.kubernetes.io/part-of: argocd name: applications.argoproj.io spec: group: argoproj.io names: kind: Application listKind: ApplicationList plural: applications shortNames: - app - apps singular: application scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .status.sync.status name: Sync Status type: string - jsonPath: .status.health.status name: Health Status type: string - jsonPath: .status.sync.revision name: Revision priority: 10 type: string name: v1alpha1 schema: openAPIV3Schema: description: Application is a definition of Application resource. 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 operation: description: Operation contains information about a requested or running operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object spec: description: ApplicationSpec represents desired application state. Contains link to repository with application definition and additional parameters link definition revision. properties: destination: description: Destination is a reference to the target Kubernetes server and namespace properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object ignoreDifferences: description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: description: Info contains a list of information (URLs, email addresses, and plain text) that relates to the application items: properties: name: type: string value: type: string required: - name - value type: object type: array project: description: Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project. type: string revisionHistoryLimit: description: RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions. This should only be changed in exceptional circumstances. Setting to zero will store no history. This will reduce storage used. Increasing will increase the space used to store the history, so we do not recommend increasing it. Default is 10. format: int64 type: integer source: description: Source is a reference to the location of the application's manifests or chart properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the location of the application's manifests or chart items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncPolicy: description: SyncPolicy controls when and how a sync will be performed properties: automated: description: Automated will keep an application synced to the target revision properties: allowEmpty: description: 'AllowEmpty allows apps have zero live resources (default: false)' type: boolean prune: description: 'Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false)' type: boolean selfHeal: description: 'SelfHeal specifies whether to revert resources back to their desired state upon modification in the cluster (default: false)' type: boolean type: object managedNamespaceMetadata: description: ManagedNamespaceMetadata controls metadata in the given namespace (if CreateNamespace=true) properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: description: Retry controls failed sync retry behavior properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object syncOptions: description: Options allow you to specify whole app sync-options items: type: string type: array type: object required: - destination - project type: object status: description: ApplicationStatus contains status information for the application properties: conditions: description: Conditions is a list of currently observed application conditions items: description: ApplicationCondition contains details about an application condition, which is usually an error or warning properties: lastTransitionTime: description: LastTransitionTime is the time the condition was last observed format: date-time type: string message: description: Message contains human-readable message indicating details about condition type: string type: description: Type is an application condition type type: string required: - message - type type: object type: array controllerNamespace: description: ControllerNamespace indicates the namespace in which the application controller is located type: string health: description: Health contains information about the application's current health status properties: message: description: Message is a human-readable informational message describing the health status type: string status: description: Status holds the status code of the application or resource type: string type: object history: description: History contains information about the application's sync history items: description: RevisionHistory contains history information about a previous sync properties: deployStartedAt: description: DeployStartedAt holds the time the sync operation started format: date-time type: string deployedAt: description: DeployedAt holds the time the sync operation completed format: date-time type: string id: description: ID is an auto incrementing identifier of the RevisionHistory format: int64 type: integer revision: description: Revision holds the revision the sync was performed against type: string revisions: description: Revisions holds the revision of each source in sources field the sync was performed against items: type: string type: array source: description: Source is a reference to the application source used for the sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application sources used for the sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - deployedAt - id type: object type: array observedAt: description: 'ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field' format: date-time type: string operationState: description: OperationState contains information about any ongoing operations, such as a sync properties: finishedAt: description: FinishedAt contains time of operation completion format: date-time type: string message: description: Message holds any pertinent messages when attempting to perform operation (typically errors). type: string operation: description: Operation is the original requested operation properties: info: description: Info is a list of informational items for this operation items: properties: name: type: string value: type: string required: - name - value type: object type: array initiatedBy: description: InitiatedBy contains information about who initiated the operations properties: automated: description: Automated is set to true if operation was initiated automatically by the application controller. type: boolean username: description: Username contains the name of a user who started operation type: string type: object retry: description: Retry controls the strategy to apply if a sync fails properties: backoff: description: Backoff controls how to backoff on subsequent retries of failed syncs properties: duration: description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") type: string factor: description: Factor is a factor to multiply the base duration after each failed retry format: int64 type: integer maxDuration: description: MaxDuration is the maximum amount of time allowed for the backoff strategy type: string type: object limit: description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. format: int64 type: integer type: object sync: description: Sync contains parameters for the operation properties: dryRun: description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync type: boolean manifests: description: Manifests is an optional field that overrides sync source with a local directory for development items: type: string type: array prune: description: Prune specifies to delete resources from the cluster that are no longer tracked in git type: boolean resources: description: Resources describes which resources shall be part of the sync items: description: SyncOperationResource contains resources to sync. properties: group: type: string kind: type: string name: type: string namespace: type: string required: - kind - name type: object type: array revision: description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. type: string revisions: description: Revisions is the list of revision (Git) or chart version (Helm) which to sync each source in sources field for the application to If omitted, will use the revision specified in app spec. items: type: string type: array source: description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array syncOptions: description: SyncOptions provide per-sync sync-options, e.g. Validate=false items: type: string type: array syncStrategy: description: SyncStrategy describes how to perform the sync properties: apply: description: Apply will perform a `kubectl apply` to perform the sync. properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object hook: description: Hook will submit any referenced resources to perform the sync. This is the default strategy properties: force: description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. type: boolean type: object type: object type: object type: object phase: description: Phase is the current phase of the operation type: string retryCount: description: RetryCount contains time of operation retries format: int64 type: integer startedAt: description: StartedAt contains time of operation start format: date-time type: string syncResult: description: SyncResult is the result of a Sync operation properties: managedNamespaceMetadata: description: ManagedNamespaceMetadata contains the current sync state of managed namespace metadata properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object resources: description: Resources contains a list of sync result items for each individual resource in a sync operation items: description: ResourceResult holds the operation result details of a specific resource properties: group: description: Group specifies the API group of the resource type: string hookPhase: description: HookPhase contains the state of any operation associated with this resource OR hook This can also contain values for non-hook resources. type: string hookType: description: HookType specifies the type of the hook. Empty for non-hook resources type: string kind: description: Kind specifies the API kind of the resource type: string message: description: Message contains an informational or error message for the last sync OR operation type: string name: description: Name specifies the name of the resource type: string namespace: description: Namespace specifies the target namespace of the resource type: string status: description: Status holds the final result of the sync. Will be empty if the resources is yet to be applied/pruned and is always zero-value for hooks type: string syncPhase: description: SyncPhase indicates the particular phase of the sync that this result was acquired in type: string version: description: Version specifies the API version of the resource type: string required: - group - kind - name - namespace - version type: object type: array revision: description: Revision holds the revision this sync operation was performed to type: string revisions: description: Revisions holds the revision this sync operation was performed for respective indexed source in sources field items: type: string type: array source: description: Source records the application source information of the sync, used for comparing auto-sync properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Source records the application source information of the sync, used for comparing auto-sync items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - revision type: object required: - operation - phase - startedAt type: object reconciledAt: description: ReconciledAt indicates when the application state was reconciled using the latest git version format: date-time type: string resourceHealthSource: description: 'ResourceHealthSource indicates where the resource health status is stored: inline if not set or appTree' type: string resources: description: Resources is a list of Kubernetes resources managed by this application items: description: 'ResourceStatus holds the current sync and health status of a resource TODO: describe members of this type' properties: group: type: string health: description: HealthStatus contains information about the currently observed health state of an application or resource properties: message: description: Message is a human-readable informational message describing the health status type: string status: description: Status holds the status code of the application or resource type: string type: object hook: type: boolean kind: type: string name: type: string namespace: type: string requiresPruning: type: boolean status: description: SyncStatusCode is a type which represents possible comparison results type: string syncWave: format: int64 type: integer version: type: string type: object type: array sourceType: description: SourceType specifies the type of this application type: string sourceTypes: description: SourceTypes specifies the type of the sources included in the application items: description: ApplicationSourceType specifies the type of the application's source type: string type: array summary: description: Summary contains a list of URLs and container images used by this application properties: externalURLs: description: ExternalURLs holds all external URLs of application child resources. items: type: string type: array images: description: Images holds all images of application child resources. items: type: string type: array type: object sync: description: Sync contains information about the application's current sync status properties: comparedTo: description: ComparedTo contains information about what has been compared properties: destination: description: Destination is a reference to the application's destination used for comparison properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object ignoreDifferences: description: IgnoreDifferences is a reference to the application's ignored differences used for comparison items: description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: description: ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the desired state defined in the SCM and won't be displayed in diffs items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array source: description: Source is a reference to the application's source used for comparison properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object sources: description: Sources is a reference to the application's multiple sources used for comparison items: description: ApplicationSource contains all required information about the source of an application properties: chart: description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. type: string directory: description: Directory holds path/directory specific options properties: exclude: description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation type: string include: description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation type: string jsonnet: description: Jsonnet holds options specific to Jsonnet properties: extVars: description: ExtVars is a list of Jsonnet External Variables items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: description: Additional library search dirs items: type: string type: array tlas: description: TLAS is a list of Jsonnet Top-level Arguments items: description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: description: Recurse specifies whether to scan a directory recursively for manifests type: boolean type: object helm: description: Helm holds helm specific options properties: fileParameters: description: FileParameters are file parameters to the helm template items: description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation properties: name: description: Name is the name of the Helm parameter type: string path: description: Path is the path to the file containing the values for the Helm parameter type: string type: object type: array ignoreMissingValueFiles: description: IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values type: boolean parameters: description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation items: description: HelmParameter is a parameter that's passed to helm template during manifest generation properties: forceString: description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings type: boolean name: description: Name is the name of the Helm parameter type: string value: description: Value is the value for the Helm parameter type: string type: object type: array passCredentials: description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) type: boolean releaseName: description: ReleaseName is the Helm release name to use. If omitted it will use the application name type: string skipCrds: description: SkipCrds skips custom resource definition installation step (Helm's --skip-crds) type: boolean valueFiles: description: ValuesFiles is a list of Helm value files to use when generating a template items: type: string type: array values: description: Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other. type: string valuesObject: description: ValuesObject specifies Helm values to be passed to helm template, defined as a map. This takes precedence over Values. type: object x-kubernetes-preserve-unknown-fields: true version: description: Version is the Helm version to use for templating ("3") type: string type: object kustomize: description: Kustomize holds kustomize specific options properties: commonAnnotations: additionalProperties: type: string description: CommonAnnotations is a list of additional annotations to add to rendered manifests type: object commonAnnotationsEnvsubst: description: CommonAnnotationsEnvsubst specifies whether to apply env variables substitution for annotation values type: boolean commonLabels: additionalProperties: type: string description: CommonLabels is a list of additional labels to add to rendered manifests type: object forceCommonAnnotations: description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps type: boolean forceCommonLabels: description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps type: boolean images: description: Images is a list of Kustomize image override specifications items: description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: type: string type: array namePrefix: description: NamePrefix is a prefix appended to resources for Kustomize apps type: string nameSuffix: description: NameSuffix is a suffix appended to resources for Kustomize apps type: string namespace: description: Namespace sets the namespace that Kustomize adds to all resources type: string replicas: description: Replicas is a list of Kustomize Replicas override specifications items: properties: count: anyOf: - type: integer - type: string description: Number of replicas x-kubernetes-int-or-string: true name: description: Name of Deployment or StatefulSet type: string required: - count - name type: object type: array version: description: Version controls which version of Kustomize to use for rendering manifests type: string type: object path: description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. type: string plugin: description: Plugin holds config management plugin specific options properties: env: description: Env is a list of environment variable entries items: description: EnvEntry represents an entry in the application's environment properties: name: description: Name is the name of the variable, usually expressed in uppercase type: string value: description: Value is the value of the variable type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: description: Array is the value of an array type parameter. items: type: string type: array map: additionalProperties: type: string description: Map is the value of a map type parameter. type: object name: description: Name is the name identifying a parameter. type: string string: description: String_ is the value of a string type parameter. type: string type: object type: array type: object ref: description: Ref is reference to another source within sources field. This field will not be used if used with a `source` tag. type: string repoURL: description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests type: string targetRevision: description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. type: string required: - repoURL type: object type: array required: - destination type: object revision: description: Revision contains information about the revision the comparison has been performed to type: string revisions: description: Revisions contains information about the revisions of multiple sources the comparison has been performed to items: type: string type: array status: description: Status is the sync state of the comparison type: string required: - status type: object type: object required: - metadata - spec type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: applicationsets.argoproj.io app.kubernetes.io/part-of: argocd name: applicationsets.argoproj.io spec: group: argoproj.io names: kind: ApplicationSet listKind: ApplicationSetList plural: applicationsets shortNames: - appset - appsets singular: applicationset scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: properties: apiVersion: type: string kind: type: string metadata: type: object spec: properties: applyNestedSelectors: type: boolean generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators type: object merge: properties: generators: items: properties: clusterDecisionResource: properties: configMapRef: type: string labelSelector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object name: type: string requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object clusters: properties: selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object git: properties: directories: items: properties: exclude: type: boolean path: type: string required: - path type: object type: array files: items: properties: path: type: string required: - path type: object type: array pathParamPrefix: type: string repoURL: type: string requeueAfterSeconds: format: int64 type: integer revision: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - repoURL - revision type: object list: properties: elements: items: x-kubernetes-preserve-unknown-fields: true type: array elementsYaml: type: string template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - elements type: object matrix: x-kubernetes-preserve-unknown-fields: true merge: x-kubernetes-preserve-unknown-fields: true plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array mergeKeys: items: type: string type: array template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators - mergeKeys type: object plugin: properties: configMapRef: properties: name: type: string required: - name type: object input: properties: parameters: additionalProperties: x-kubernetes-preserve-unknown-fields: true type: object type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object required: - configMapRef type: object pullRequest: properties: azuredevops: properties: api: type: string labels: items: type: string type: array organization: type: string project: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization - project - repo type: object bitbucket: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object bearerToken: properties: tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - tokenRef type: object owner: type: string repo: type: string required: - owner - repo type: object bitbucketServer: properties: api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string repo: type: string required: - api - project - repo type: object filters: items: properties: branchMatch: type: string targetBranchMatch: type: string type: object type: array gitea: properties: api: type: string insecure: type: boolean owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner - repo type: object github: properties: api: type: string appSecretName: type: string labels: items: type: string type: array owner: type: string repo: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - owner - repo type: object gitlab: properties: api: type: string insecure: type: boolean labels: items: type: string type: array project: type: string pullRequestState: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - project type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object type: object scmProvider: properties: awsCodeCommit: properties: allBranches: type: boolean region: type: string role: type: string tagFilters: items: properties: key: type: string value: type: string required: - key type: object type: array type: object azureDevOps: properties: accessTokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object allBranches: type: boolean api: type: string organization: type: string teamProject: type: string required: - accessTokenRef - organization - teamProject type: object bitbucket: properties: allBranches: type: boolean appPasswordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object owner: type: string user: type: string required: - appPasswordRef - owner - user type: object bitbucketServer: properties: allBranches: type: boolean api: type: string basicAuth: properties: passwordRef: properties: key: type: string secretName: type: string required: - key - secretName type: object username: type: string required: - passwordRef - username type: object project: type: string required: - api - project type: object cloneProtocol: type: string filters: items: properties: branchMatch: type: string labelMatch: type: string pathsDoNotExist: items: type: string type: array pathsExist: items: type: string type: array repositoryMatch: type: string type: object type: array gitea: properties: allBranches: type: boolean api: type: string insecure: type: boolean owner: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - api - owner type: object github: properties: allBranches: type: boolean api: type: string appSecretName: type: string organization: type: string tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - organization type: object gitlab: properties: allBranches: type: boolean api: type: string group: type: string includeSubgroups: type: boolean insecure: type: boolean tokenRef: properties: key: type: string secretName: type: string required: - key - secretName type: object required: - group type: object requeueAfterSeconds: format: int64 type: integer template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object values: additionalProperties: type: string type: object type: object selector: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array required: - key - operator type: object type: array matchLabels: additionalProperties: type: string type: object type: object type: object type: array goTemplate: type: boolean goTemplateOptions: items: type: string type: array preservedFields: properties: annotations: items: type: string type: array type: object strategy: properties: rollingSync: properties: steps: items: properties: matchExpressions: items: properties: key: type: string operator: type: string values: items: type: string type: array type: object type: array maxUpdate: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true type: object type: array type: object type: type: string type: object syncPolicy: properties: applicationsSync: enum: - create-only - create-update - create-delete - sync type: string preserveResourcesOnDeletion: type: boolean type: object template: properties: metadata: properties: annotations: additionalProperties: type: string type: object finalizers: items: type: string type: array labels: additionalProperties: type: string type: object name: type: string namespace: type: string type: object spec: properties: destination: properties: name: type: string namespace: type: string server: type: string type: object ignoreDifferences: items: properties: group: type: string jqPathExpressions: items: type: string type: array jsonPointers: items: type: string type: array kind: type: string managedFieldsManagers: items: type: string type: array name: type: string namespace: type: string required: - kind type: object type: array info: items: properties: name: type: string value: type: string required: - name - value type: object type: array project: type: string revisionHistoryLimit: format: int64 type: integer source: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object sources: items: properties: chart: type: string directory: properties: exclude: type: string include: type: string jsonnet: properties: extVars: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array libs: items: type: string type: array tlas: items: properties: code: type: boolean name: type: string value: type: string required: - name - value type: object type: array type: object recurse: type: boolean type: object helm: properties: fileParameters: items: properties: name: type: string path: type: string type: object type: array ignoreMissingValueFiles: type: boolean parameters: items: properties: forceString: type: boolean name: type: string value: type: string type: object type: array passCredentials: type: boolean releaseName: type: string skipCrds: type: boolean valueFiles: items: type: string type: array values: type: string valuesObject: type: object x-kubernetes-preserve-unknown-fields: true version: type: string type: object kustomize: properties: commonAnnotations: additionalProperties: type: string type: object commonAnnotationsEnvsubst: type: boolean commonLabels: additionalProperties: type: string type: object forceCommonAnnotations: type: boolean forceCommonLabels: type: boolean images: items: type: string type: array namePrefix: type: string nameSuffix: type: string namespace: type: string replicas: items: properties: count: anyOf: - type: integer - type: string x-kubernetes-int-or-string: true name: type: string required: - count - name type: object type: array version: type: string type: object path: type: string plugin: properties: env: items: properties: name: type: string value: type: string required: - name - value type: object type: array name: type: string parameters: items: properties: array: items: type: string type: array map: additionalProperties: type: string type: object name: type: string string: type: string type: object type: array type: object ref: type: string repoURL: type: string targetRevision: type: string required: - repoURL type: object type: array syncPolicy: properties: automated: properties: allowEmpty: type: boolean prune: type: boolean selfHeal: type: boolean type: object managedNamespaceMetadata: properties: annotations: additionalProperties: type: string type: object labels: additionalProperties: type: string type: object type: object retry: properties: backoff: properties: duration: type: string factor: format: int64 type: integer maxDuration: type: string type: object limit: format: int64 type: integer type: object syncOptions: items: type: string type: array type: object required: - destination - project type: object required: - metadata - spec type: object required: - generators - template type: object status: properties: applicationStatus: items: properties: application: type: string lastTransitionTime: format: date-time type: string message: type: string status: type: string step: type: string required: - application - message - status - step type: object type: array conditions: items: properties: lastTransitionTime: format: date-time type: string message: type: string reason: type: string status: type: string type: type: string required: - message - reason - status - type type: object type: array type: object required: - metadata - spec type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app.kubernetes.io/name: appprojects.argoproj.io app.kubernetes.io/part-of: argocd name: appprojects.argoproj.io spec: group: argoproj.io names: kind: AppProject listKind: AppProjectList plural: appprojects shortNames: - appproj - appprojs singular: appproject scope: Namespaced versions: - name: v1alpha1 schema: openAPIV3Schema: description: 'AppProject provides a logical grouping of applications, providing controls for: * where the apps may deploy to (cluster whitelist) * what may be deployed (repository whitelist, resource whitelist/blacklist) * who can access these applications (roles, OIDC group claims bindings) * and what they can do (RBAC policies) * automation access to these roles (JWT tokens)' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: AppProjectSpec is the specification of an AppProject properties: clusterResourceBlacklist: description: ClusterResourceBlacklist contains list of blacklisted cluster level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array clusterResourceWhitelist: description: ClusterResourceWhitelist contains list of whitelisted cluster level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array description: description: Description contains optional project description type: string destinations: description: Destinations contains list of destinations available for deployment items: description: ApplicationDestination holds information about the application's destination properties: name: description: Name is an alternate way of specifying the target cluster by its symbolic name type: string namespace: description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace type: string server: description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API type: string type: object type: array namespaceResourceBlacklist: description: NamespaceResourceBlacklist contains list of blacklisted namespace level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array namespaceResourceWhitelist: description: NamespaceResourceWhitelist contains list of whitelisted namespace level resources items: description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types properties: group: type: string kind: type: string required: - group - kind type: object type: array orphanedResources: description: OrphanedResources specifies if controller should monitor orphaned resources of apps in this project properties: ignore: description: Ignore contains a list of resources that are to be excluded from orphaned resources monitoring items: description: OrphanedResourceKey is a reference to a resource to be ignored from properties: group: type: string kind: type: string name: type: string type: object type: array warn: description: Warn indicates if warning condition should be created for apps which have orphaned resources type: boolean type: object permitOnlyProjectScopedClusters: description: PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped type: boolean roles: description: Roles are user defined RBAC roles associated with this project items: description: ProjectRole represents a role that has access to a project properties: description: description: Description is a description of the role type: string groups: description: Groups are a list of OIDC group claims bound to this role items: type: string type: array jwtTokens: description: JWTTokens are a list of generated JWT tokens bound to this role items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array name: description: Name is a name for this role type: string policies: description: Policies Stores a list of casbin formatted strings that define access policies for the role in the project items: type: string type: array required: - name type: object type: array signatureKeys: description: SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync items: description: SignatureKey is the specification of a key required to verify commit signatures with properties: keyID: description: The ID of the key in hexadecimal notation type: string required: - keyID type: object type: array sourceNamespaces: description: SourceNamespaces defines the namespaces application resources are allowed to be created in items: type: string type: array sourceRepos: description: SourceRepos contains list of repository URLs which can be used for deployment items: type: string type: array syncWindows: description: SyncWindows controls when syncs can be run for apps in this project items: description: SyncWindow contains the kind, time, duration and attributes that are used to assign the syncWindows to apps properties: applications: description: Applications contains a list of applications that the window will apply to items: type: string type: array clusters: description: Clusters contains a list of clusters that the window will apply to items: type: string type: array duration: description: Duration is the amount of time the sync window will be open type: string kind: description: Kind defines if the window allows or blocks syncs type: string manualSync: description: ManualSync enables manual syncs when they would otherwise be blocked type: boolean namespaces: description: Namespaces contains a list of namespaces that the window will apply to items: type: string type: array schedule: description: Schedule is the time the window will begin, specified in cron format type: string timeZone: description: TimeZone of the sync that will be applied to the schedule type: string type: object type: array type: object status: description: AppProjectStatus contains status information for AppProject CRs properties: jwtTokensByRole: additionalProperties: description: JWTTokens represents a list of JWT tokens properties: items: items: description: JWTToken holds the issuedAt and expiresAt values of a token properties: exp: format: int64 type: integer iat: format: int64 type: integer id: type: string required: - iat type: object type: array type: object description: JWTTokensByRole contains a list of JWT tokens issued for a given role type: object type: object required: - metadata - spec type: object served: true storage: true --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - argoproj.io resources: - applications - appprojects verbs: - create - get - list - watch - update - patch - delete - apiGroups: - "" resources: - events verbs: - create - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller rules: - apiGroups: - argoproj.io resources: - applications - applicationsets - applicationsets/finalizers verbs: - create - delete - get - list - patch - update - watch - apiGroups: - argoproj.io resources: - appprojects verbs: - get - apiGroups: - argoproj.io resources: - applicationsets/status verbs: - get - patch - update - apiGroups: - "" resources: - events verbs: - create - get - list - patch - watch - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch - apiGroups: - apps - extensions resources: - deployments verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller rules: - apiGroups: - argoproj.io resources: - applications - appprojects verbs: - get - list - watch - update - patch - apiGroups: - "" resources: - configmaps - secrets verbs: - list - watch - apiGroups: - "" resourceNames: - argocd-notifications-cm resources: - configmaps verbs: - get - apiGroups: - "" resourceNames: - argocd-notifications-secret resources: - secrets verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - "" resources: - secrets - configmaps verbs: - create - get - list - watch - update - patch - delete - apiGroups: - argoproj.io resources: - applications - appprojects - applicationsets verbs: - create - get - list - watch - update - delete - patch - apiGroups: - "" resources: - events verbs: - create - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller rules: - apiGroups: - '*' resources: - '*' verbs: - '*' - nonResourceURLs: - '*' verbs: - '*' --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server rules: - apiGroups: - '*' resources: - '*' verbs: - delete - get - patch - apiGroups: - "" resources: - events verbs: - list - apiGroups: - "" resources: - pods - pods/log verbs: - get - apiGroups: - argoproj.io resources: - applications verbs: - get - list - watch - apiGroups: - batch resources: - jobs verbs: - create - apiGroups: - argoproj.io resources: - workflows verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-applicationset-controller subjects: - kind: ServiceAccount name: argocd-applicationset-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-dex-server subjects: - kind: ServiceAccount name: argocd-dex-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-notifications-controller subjects: - kind: ServiceAccount name: argocd-notifications-controller --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: argocd-server subjects: - kind: ServiceAccount name: argocd-server --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-application-controller subjects: - kind: ServiceAccount name: argocd-application-controller namespace: argocd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: argocd-server subjects: - kind: ServiceAccount name: argocd-server namespace: argocd --- apiVersion: v1 data: application.resourceTrackingMethod: annotation resource.exclusions: | - kinds: - ProviderConfigUsage apiGroups: - "*" kind: ConfigMap metadata: labels: Test: Data app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd name: argocd-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-cmd-params-cm app.kubernetes.io/part-of: argocd name: argocd-cmd-params-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-gpg-keys-cm app.kubernetes.io/part-of: argocd name: argocd-gpg-keys-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-rbac-cm app.kubernetes.io/part-of: argocd name: argocd-rbac-cm --- apiVersion: v1 data: ssh_known_hosts: | # This file was automatically generated by hack/update-ssh-known-hosts.sh. DO NOT EDIT [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl [ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE= bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M= github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY= gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9 ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-ssh-known-hosts-cm app.kubernetes.io/part-of: argocd name: argocd-ssh-known-hosts-cm --- apiVersion: v1 kind: ConfigMap metadata: labels: app.kubernetes.io/name: argocd-tls-certs-cm app.kubernetes.io/part-of: argocd name: argocd-tls-certs-cm --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-secret type: Opaque --- apiVersion: v1 kind: Secret metadata: labels: app.kubernetes.io/name: argocd-secret app.kubernetes.io/part-of: argocd name: argocd-secret type: Opaque --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: ports: - name: webhook port: 7000 protocol: TCP targetPort: webhook - name: metrics port: 8080 protocol: TCP targetPort: metrics selector: app.kubernetes.io/name: argocd-applicationset-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: ports: - name: http port: 5556 protocol: TCP targetPort: 5556 - name: grpc port: 5557 protocol: TCP targetPort: 5557 - name: metrics port: 5558 protocol: TCP targetPort: 5558 selector: app.kubernetes.io/name: argocd-dex-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: metrics app.kubernetes.io/name: argocd-metrics app.kubernetes.io/part-of: argocd name: argocd-metrics spec: ports: - name: metrics port: 8082 protocol: TCP targetPort: 8082 selector: app.kubernetes.io/name: argocd-application-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller-metrics app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-metrics spec: ports: - name: metrics port: 9001 protocol: TCP targetPort: 9001 selector: app.kubernetes.io/name: argocd-notifications-controller --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: ports: - name: tcp-redis port: 6379 targetPort: 6379 selector: app.kubernetes.io/name: argocd-redis --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: ports: - name: server port: 8081 protocol: TCP targetPort: 8081 - name: metrics port: 8084 protocol: TCP targetPort: 8084 selector: app.kubernetes.io/name: argocd-repo-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: ports: - name: http port: 80 protocol: TCP targetPort: 8080 - name: https port: 443 protocol: TCP targetPort: 8080 selector: app.kubernetes.io/name: argocd-server --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server-metrics app.kubernetes.io/part-of: argocd name: argocd-server-metrics spec: ports: - name: metrics port: 8083 protocol: TCP targetPort: 8083 selector: app.kubernetes.io/name: argocd-server --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: applicationset-controller app.kubernetes.io/name: argocd-applicationset-controller app.kubernetes.io/part-of: argocd name: argocd-applicationset-controller spec: selector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller template: metadata: labels: app.kubernetes.io/name: argocd-applicationset-controller spec: containers: - args: - /usr/local/bin/argocd-applicationset-controller env: - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_LEADER_ELECTION valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.leader.election name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_POLICY valueFrom: configMapKeyRef: key: applicationsetcontroller.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.policy.override name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DEBUG valueFrom: configMapKeyRef: key: applicationsetcontroller.debug name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: applicationsetcontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: applicationsetcontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_DRY_RUN valueFrom: configMapKeyRef: key: applicationsetcontroller.dryrun name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.progressive.syncs name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_NEW_GIT_FILE_GLOBBING valueFrom: configMapKeyRef: key: applicationsetcontroller.enable.new.git.file.globbing name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: applicationsetcontroller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_RECONCILIATIONS valueFrom: configMapKeyRef: key: applicationsetcontroller.concurrent.reconciliations.max name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_NAMESPACES valueFrom: configMapKeyRef: key: applicationsetcontroller.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH valueFrom: configMapKeyRef: key: applicationsetcontroller.scm.root.ca.path name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS valueFrom: configMapKeyRef: key: applicationsetcontroller.allowed.scm.providers name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: argocd-applicationset-controller ports: - containerPort: 7000 name: webhook - containerPort: 8080 name: metrics securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /tmp name: tmp - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls serviceAccountName: argocd-applicationset-controller volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: dex-server app.kubernetes.io/name: argocd-dex-server app.kubernetes.io/part-of: argocd name: argocd-dex-server spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-dex-server template: metadata: labels: app.kubernetes.io/name: argocd-dex-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - command: - /shared/argocd-dex - rundex env: - name: ARGOCD_DEX_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: dexserver.disable.tls name: argocd-cmd-params-cm optional: true image: ghcr.io/dexidp/dex:v2.37.0 imagePullPolicy: Always name: dex ports: - containerPort: 5556 - containerPort: 5557 - containerPort: 5558 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig - mountPath: /tls name: argocd-dex-server-tls initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /shared/argocd-dex image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files - mountPath: /tmp name: dexconfig serviceAccountName: argocd-dex-server volumes: - emptyDir: {} name: static-files - emptyDir: {} name: dexconfig - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller spec: replicas: 0 selector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller strategy: type: Recreate template: metadata: labels: app.kubernetes.io/name: argocd-notifications-controller spec: containers: - args: - /usr/local/bin/argocd-notifications env: - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: notificationscontroller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_NOTIFICATIONS_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: tcpSocket: port: 9001 name: argocd-notifications-controller securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true volumeMounts: - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls workingDir: /app securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: redis app.kubernetes.io/name: argocd-redis app.kubernetes.io/part-of: argocd name: argocd-redis spec: selector: matchLabels: app.kubernetes.io/name: argocd-redis template: metadata: labels: app.kubernetes.io/name: argocd-redis spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-redis topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - --save - "" - --appendonly - "no" image: redis:7.0.11-alpine imagePullPolicy: Always name: redis ports: - containerPort: 6379 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true securityContext: runAsNonRoot: true runAsUser: 999 seccompProfile: type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: repo-server app.kubernetes.io/name: argocd-repo-server app.kubernetes.io/part-of: argocd name: argocd-repo-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-repo-server template: metadata: labels: app.kubernetes.io/name: argocd-repo-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 automountServiceAccountToken: false containers: - args: - /usr/local/bin/argocd-repo-server env: - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_REPO_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: reposerver.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LOGLEVEL valueFrom: configMapKeyRef: key: reposerver.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: reposerver.parallelism.limit name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: reposerver.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_LISTEN_METRICS_ADDRESS valueFrom: configMapKeyRef: key: reposerver.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_TLS valueFrom: configMapKeyRef: key: reposerver.disable.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: reposerver.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: reposerver.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.repo.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: reposerver.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE valueFrom: configMapKeyRef: key: reposerver.max.combined.directory.manifests.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS valueFrom: configMapKeyRef: key: reposerver.plugin.tar.exclusions name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS valueFrom: configMapKeyRef: key: reposerver.allow.oob.symlinks name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_TAR_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.tar.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.streamed.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE valueFrom: configMapKeyRef: key: reposerver.disable.helm.manifest.max.extracted.size name: argocd-cmd-params-cm optional: true - name: ARGOCD_GIT_MODULES_ENABLED valueFrom: configMapKeyRef: key: reposerver.enable.git.submodule name: argocd-cmd-params-cm optional: true - name: HELM_CACHE_HOME value: /helm-working-dir - name: HELM_CONFIG_HOME value: /helm-working-dir - name: HELM_DATA_HOME value: /helm-working-dir image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: failureThreshold: 3 httpGet: path: /healthz?full=true port: 8084 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 name: argocd-repo-server ports: - containerPort: 8081 - containerPort: 8084 readinessProbe: httpGet: path: /healthz port: 8084 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/gpg/source name: gpg-keys - mountPath: /app/config/gpg/keys name: gpg-keyring - mountPath: /app/config/reposerver/tls name: argocd-repo-server-tls - mountPath: /tmp name: tmp - mountPath: /helm-working-dir name: helm-working-dir - mountPath: /home/argocd/cmp-server/plugins name: plugins initContainers: - command: - /bin/cp - -n - /usr/local/bin/argocd - /var/run/argocd/argocd-cmp-server image: quay.io/argoproj/argocd:v2.8.7 name: copyutil securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files serviceAccountName: argocd-repo-server volumes: - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - configMap: name: argocd-gpg-keys-cm name: gpg-keys - emptyDir: {} name: gpg-keyring - emptyDir: {} name: tmp - emptyDir: {} name: helm-working-dir - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - emptyDir: {} name: var-files - emptyDir: {} name: plugins --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: server app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd name: argocd-server spec: selector: matchLabels: app.kubernetes.io/name: argocd-server template: metadata: labels: app.kubernetes.io/name: argocd-server spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-server topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-server - '' env: - name: ARGOCD_SERVER_INSECURE valueFrom: configMapKeyRef: key: server.insecure name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_BASEHREF valueFrom: configMapKeyRef: key: server.basehref name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ROOTPATH valueFrom: configMapKeyRef: key: server.rootpath name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOGFORMAT valueFrom: configMapKeyRef: key: server.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOG_LEVEL valueFrom: configMapKeyRef: key: server.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER valueFrom: configMapKeyRef: key: server.dex.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DISABLE_AUTH valueFrom: configMapKeyRef: key: server.disable.auth name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_GZIP valueFrom: configMapKeyRef: key: server.enable.gzip name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: server.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_X_FRAME_OPTIONS valueFrom: configMapKeyRef: key: server.x.frame.options name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONTENT_SECURITY_POLICY valueFrom: configMapKeyRef: key: server.content.security.policy name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: server.dex.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_DEX_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: server.dex.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MIN_VERSION valueFrom: configMapKeyRef: key: server.tls.minversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_MAX_VERSION valueFrom: configMapKeyRef: key: server.tls.maxversion name: argocd-cmd-params-cm optional: true - name: ARGOCD_TLS_CIPHERS valueFrom: configMapKeyRef: key: server.tls.ciphers name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_CONNECTION_STATUS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.connection.status.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OIDC_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.oidc.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LOGIN_ATTEMPTS_EXPIRATION valueFrom: configMapKeyRef: key: server.login.attempts.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_STATIC_ASSETS valueFrom: configMapKeyRef: key: server.staticassets name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: server.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_MAX_COOKIE_NUMBER valueFrom: configMapKeyRef: key: server.http.cookie.maxnumber name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_METRICS_LISTEN_ADDRESS valueFrom: configMapKeyRef: key: server.metrics.listen.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_SERVER_ENABLE_PROXY_EXTENSION valueFrom: configMapKeyRef: key: server.enable.proxy.extension name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always livenessProbe: httpGet: path: /healthz?full=true port: 8080 initialDelaySeconds: 3 periodSeconds: 30 timeoutSeconds: 5 name: argocd-server ports: - containerPort: 8080 - containerPort: 8083 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 3 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts - mountPath: /app/config/tls name: tls-certs - mountPath: /app/config/server/tls name: argocd-repo-server-tls - mountPath: /app/config/dex/tls name: argocd-dex-server-tls - mountPath: /home/argocd name: plugins-home - mountPath: /tmp name: tmp serviceAccountName: argocd-server volumes: - emptyDir: {} name: plugins-home - emptyDir: {} name: tmp - configMap: name: argocd-ssh-known-hosts-cm name: ssh-known-hosts - configMap: name: argocd-tls-certs-cm name: tls-certs - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls - name: argocd-dex-server-tls secret: items: - key: tls.crt path: tls.crt - key: ca.crt path: ca.crt optional: true secretName: argocd-dex-server-tls --- apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/component: application-controller app.kubernetes.io/name: argocd-application-controller app.kubernetes.io/part-of: argocd name: argocd-application-controller spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: argocd-application-controller serviceName: argocd-application-controller template: metadata: labels: app.kubernetes.io/name: argocd-application-controller spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller topologyKey: kubernetes.io/hostname weight: 100 - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/part-of: argocd topologyKey: kubernetes.io/hostname weight: 5 containers: - args: - /usr/local/bin/argocd-application-controller env: - name: ARGOCD_CONTROLLER_REPLICAS value: "1" - name: ARGOCD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.reconciliation name: argocd-cm optional: true - name: ARGOCD_HARD_RECONCILIATION_TIMEOUT valueFrom: configMapKeyRef: key: timeout.hard.reconciliation name: argocd-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER valueFrom: configMapKeyRef: key: repo.server name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.repo.server.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_STATUS_PROCESSORS valueFrom: configMapKeyRef: key: controller.status.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OPERATION_PROCESSORS valueFrom: configMapKeyRef: key: controller.operation.processors name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGFORMAT valueFrom: configMapKeyRef: key: controller.log.format name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_LOGLEVEL valueFrom: configMapKeyRef: key: controller.log.level name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.metrics.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS valueFrom: configMapKeyRef: key: controller.self.heal.timeout.seconds name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT valueFrom: configMapKeyRef: key: controller.repo.server.plaintext name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS valueFrom: configMapKeyRef: key: controller.repo.server.strict.tls name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_PERSIST_RESOURCE_HEALTH valueFrom: configMapKeyRef: key: controller.resource.health.persist name: argocd-cmd-params-cm optional: true - name: ARGOCD_APP_STATE_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.app.state.cache.expiration name: argocd-cmd-params-cm optional: true - name: REDIS_SERVER valueFrom: configMapKeyRef: key: redis.server name: argocd-cmd-params-cm optional: true - name: REDIS_COMPRESSION valueFrom: configMapKeyRef: key: redis.compression name: argocd-cmd-params-cm optional: true - name: REDISDB valueFrom: configMapKeyRef: key: redis.db name: argocd-cmd-params-cm optional: true - name: ARGOCD_DEFAULT_CACHE_EXPIRATION valueFrom: configMapKeyRef: key: controller.default.cache.expiration name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS valueFrom: configMapKeyRef: key: otlp.address name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_NAMESPACES valueFrom: configMapKeyRef: key: application.namespaces name: argocd-cmd-params-cm optional: true - name: ARGOCD_CONTROLLER_SHARDING_ALGORITHM valueFrom: configMapKeyRef: key: controller.sharding.algorithm name: argocd-cmd-params-cm optional: true - name: ARGOCD_APPLICATION_CONTROLLER_KUBECTL_PARALLELISM_LIMIT valueFrom: configMapKeyRef: key: controller.kubectl.parallelism.limit name: argocd-cmd-params-cm optional: true image: quay.io/argoproj/argocd:v2.8.7 imagePullPolicy: Always name: argocd-application-controller ports: - containerPort: 8082 readinessProbe: httpGet: path: /healthz port: 8082 initialDelaySeconds: 5 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls - mountPath: /home/argocd name: argocd-home workingDir: /home/argocd serviceAccountName: argocd-application-controller volumes: - emptyDir: {} name: argocd-home - name: argocd-repo-server-tls secret: items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key - key: ca.crt path: ca.crt optional: true secretName: argocd-repo-server-tls --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-application-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 8082 podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-applicationset-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 7000 protocol: TCP - port: 8080 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-dex-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server ports: - port: 5556 protocol: TCP - port: 5557 protocol: TCP - from: - namespaceSelector: {} ports: - port: 5558 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-dex-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/component: notifications-controller app.kubernetes.io/name: argocd-notifications-controller app.kubernetes.io/part-of: argocd name: argocd-notifications-controller-network-policy spec: ingress: - from: - namespaceSelector: {} ports: - port: 9001 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-redis-network-policy spec: egress: - ports: - port: 53 protocol: UDP - port: 53 protocol: TCP ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller ports: - port: 6379 protocol: TCP podSelector: matchLabels: app.kubernetes.io/name: argocd-redis policyTypes: - Ingress - Egress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-repo-server-network-policy spec: ingress: - from: - podSelector: matchLabels: app.kubernetes.io/name: argocd-server - podSelector: matchLabels: app.kubernetes.io/name: argocd-application-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-notifications-controller - podSelector: matchLabels: app.kubernetes.io/name: argocd-applicationset-controller ports: - port: 8081 protocol: TCP - from: - namespaceSelector: {} ports: - port: 8084 podSelector: matchLabels: app.kubernetes.io/name: argocd-repo-server policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: argocd-server-network-policy spec: ingress: - {} podSelector: matchLabels: app.kubernetes.io/name: argocd-server policyTypes: - Ingress ================================================ FILE: pkg/k8s/test-resources/output/nginx/install-tmpl.yaml ================================================ apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - "" resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - coordination.k8s.io resourceNames: - ingress-nginx-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - "" resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: allow-snippet-annotations: "true" proxy-buffer-size: 32k use-forwarded-headers: "true" kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 spec: containers: - args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key - --watch-ingress-without-class=true - --publish-status-address=localhost - --enable-ssl-passthrough env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.k8s.io/ingress-nginx/controller:v1.8.1@sha256:e5c4824e7375fcf2a393e1c03c293b69759af37a9ca6abdb91b13d78a93da8bd imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 hostPort: 80 name: http protocol: TCP - containerPort: 443 hostPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: true capabilities: add: - NET_BIND_SERVICE drop: - ALL runAsUser: 101 volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 0 volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create spec: containers: - args: - create - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace=$(POD_NAMESPACE) - --secret-name=ingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch spec: containers: - args: - patch - --webhook-name=ingress-nginx-admission - --namespace=$(POD_NAMESPACE) - --patch-mutating=false - --secret-name=ingress-nginx-admission - --patch-failure-policy=Fail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None --- apiVersion: v1 kind: Service metadata: labels: test: data name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http-8443 port: 8443 protocol: TCP targetPort: http - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-one --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-two ================================================ FILE: pkg/k8s/test-resources/output/nginx/install.yaml ================================================ apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - "" resources: - namespaces verbs: - get - apiGroups: - "" resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - coordination.k8s.io resourceNames: - ingress-nginx-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - "" resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: allow-snippet-annotations: "true" proxy-buffer-size: 32k use-forwarded-headers: "true" kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: test: test name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 spec: containers: - args: - /nginx-ingress-controller - --election-id=ingress-nginx-leader - --controller-class=k8s.io/ingress-nginx - --ingress-class=nginx - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook=:8443 - --validating-webhook-certificate=/usr/local/certificates/cert - --validating-webhook-key=/usr/local/certificates/key - --watch-ingress-without-class=true - --publish-status-address=localhost - --enable-ssl-passthrough env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.k8s.io/ingress-nginx/controller:v1.8.1@sha256:e5c4824e7375fcf2a393e1c03c293b69759af37a9ca6abdb91b13d78a93da8bd imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 hostPort: 80 name: http protocol: TCP - containerPort: 443 hostPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: true capabilities: add: - NET_BIND_SERVICE drop: - ALL runAsUser: 101 volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 0 volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-create spec: containers: - args: - create - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace=$(POD_NAMESPACE) - --secret-name=ingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission-patch spec: containers: - args: - patch - --webhook-name=ingress-nginx-admission - --namespace=$(POD_NAMESPACE) - --patch-mutating=false - --secret-name=ingress-nginx-admission - --patch-failure-policy=Fail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230407@sha256:543c40fd093964bc9ab509d3e791f9989963021f1e9e4c9c7b6700b02bfb227b imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.8.1 name: ingress-nginx-controller namespace: ingress-nginx spec: ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http-8443 port: 8443 protocol: TCP targetPort: http - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-one --- apiVersion: v1 stringData: test: data kind: Secret metadata: labels: Test: Data name: secret-two ================================================ FILE: pkg/k8s/util.go ================================================ package k8s import ( "embed" "github.com/cnoe-io/idpbuilder/pkg/util/files" "github.com/cnoe-io/idpbuilder/pkg/util/fs" "k8s.io/apimachinery/pkg/runtime" "os" "sigs.k8s.io/controller-runtime/pkg/client" ) func BuildCustomizedManifests(filePath, fsPath string, resourceFS embed.FS, scheme *runtime.Scheme, templateData any) ([][]byte, error) { rawResources, err := fs.ConvertFSToBytes(resourceFS, fsPath, templateData) if err != nil { return nil, err } if filePath == "" { return rawResources, nil } bs, _, err := applyOverrides(filePath, rawResources, scheme, templateData) if err != nil { return nil, err } return bs, nil } func BuildCustomizedObjects(filePath, fsPath string, resourceFS embed.FS, scheme *runtime.Scheme, templateData any) ([]client.Object, error) { rawResources, err := fs.ConvertFSToBytes(resourceFS, fsPath, templateData) if err != nil { return nil, err } if filePath == "" { return ConvertRawResourcesToObjects(scheme, rawResources) } _, objs, err := applyOverrides(filePath, rawResources, scheme, templateData) if err != nil { return nil, err } return objs, nil } func applyOverrides(filePath string, originalFiles [][]byte, scheme *runtime.Scheme, templateData any) ([][]byte, []client.Object, error) { customBS, err := os.ReadFile(filePath) if err != nil { return nil, nil, err } rendered, err := files.ApplyTemplate(customBS, templateData) if err != nil { return nil, nil, err } return ConvertYamlToObjectsWithOverride(scheme, originalFiles, rendered) } ================================================ FILE: pkg/k8s/util_test.go ================================================ package k8s import ( "bytes" "embed" "os" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/stretchr/testify/assert" ) //go:embed test-resources/* var testDataFS embed.FS func TestBuildCustomizedManifests(t *testing.T) { cases := map[string]struct { fsPath string filePath string expectedFilepath string }{ "argocd": { fsPath: "test-resources/input/argocd", filePath: "test-resources/input/argocd-cm.yaml", expectedFilepath: "test-resources/output/argocd/install.yaml", }, "nginx": { fsPath: "test-resources/input/nginx", filePath: "test-resources/input/extra.yaml", expectedFilepath: "test-resources/output/nginx/install.yaml", }, "nginx-template": { fsPath: "test-resources/input/nginx", filePath: "test-resources/input/extra.yaml.tmpl", expectedFilepath: "test-resources/output/nginx/install-tmpl.yaml", }, } for key := range cases { c := cases[key] b, err := BuildCustomizedManifests(c.filePath, c.fsPath, testDataFS, GetScheme(), v1alpha1.BuildCustomizationSpec{ Protocol: "http", Host: "cnoe.localtest.me", IngressHost: "localhost", Port: "8443", UsePathRouting: false, }) if err != nil { t.Fatalf("failed %s: %v", key, err) } expected, _ := os.ReadFile(c.expectedFilepath) expectedYamls := bytes.Split(expected, []byte{'-', '-', '-'}) testYamls := make([][]byte, 0, 10) for f := range b { y := bytes.Split(b[f], []byte{'-', '-', '-'}) testYamls = append(testYamls, y...) } if len(expectedYamls) != len(testYamls) { t.Fatalf("failed %s: number of yaml objects do not match", key) } for i := 0; i < len(expectedYamls); i++ { ok := assert.YAMLEq(t, string(expectedYamls[i]), string(testYamls[i])) if !ok { t.Fatalf("failed %s", key) } } } } ================================================ FILE: pkg/kind/cluster.go ================================================ package kind import ( "context" "errors" "fmt" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/cnoe-io/idpbuilder/pkg/util/files" "net/http" "strconv" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/go-logr/logr" "sigs.k8s.io/controller-runtime/pkg/log" kindv1alpha4 "sigs.k8s.io/kind/pkg/apis/config/v1alpha4" "sigs.k8s.io/kind/pkg/cluster" "sigs.k8s.io/kind/pkg/cluster/nodes" kindexec "sigs.k8s.io/kind/pkg/exec" "sigs.k8s.io/yaml" ) const ( ingressNginxNodeLabelKey = "ingress-ready" ingressNginxNodeLabelValue = "true" ) var ( setupLog = log.Log.WithName("setup") ) type HttpClient interface { Get(url string) (resp *http.Response, err error) } type Cluster struct { provider IProvider httpClient HttpClient name string kubeVersion string kubeConfigPath string kindConfigPath string extraPortsMapping string registryConfig []string cfg v1alpha1.BuildCustomizationSpec } type IProvider interface { List() ([]string, error) ListNodes(string) ([]nodes.Node, error) CollectLogs(string, string) error Delete(string, string) error Create(string, ...cluster.CreateOption) error ExportKubeConfig(string, string, bool) error } func (c *Cluster) getConfig() ([]byte, error) { rawConfigTempl, err := loadConfig(c.kindConfigPath, c.httpClient) if err != nil { return nil, fmt.Errorf("loading config template: %w", err) } portMappingPairs := parsePortMappings(c.extraPortsMapping) registryConfig := findRegistryConfig(c.registryConfig) registryCertsDir, err := renderRegistryCertsDir(c.cfg) if err != nil { return nil, fmt.Errorf("rendering insecure registry config: %w", err) } if len(c.registryConfig) > 0 && registryConfig == "" { return nil, errors.New("--registry-config flag used but no registry config was found") } var retBuff []byte if retBuff, err = files.ApplyTemplate(rawConfigTempl, TemplateConfig{ BuildCustomizationSpec: c.cfg, KubernetesVersion: c.kubeVersion, ExtraPortsMapping: portMappingPairs, RegistryConfig: registryConfig, RegistryCertsDir: registryCertsDir, }); err != nil { return nil, err } if c.kindConfigPath != "" { parsedCluster, err := c.ensureCorrectConfig(retBuff) if err != nil { return nil, fmt.Errorf("ensuring custom kind config is correct: %w", err) } out, err := yaml.Marshal(parsedCluster) if err != nil { return nil, fmt.Errorf("marshaling custom kind cluster config: %w", err) } return out, nil } return retBuff, nil } func NewCluster(name, kubeVersion, kubeConfigPath, kindConfigPath, extraPortsMapping string, registryConfig []string, cfg v1alpha1.BuildCustomizationSpec, cliLogger logr.Logger) (*Cluster, error) { detectOpt, err := util.DetectKindNodeProvider() if err != nil { return nil, err } provider := cluster.NewProvider(cluster.ProviderWithLogger(KindLoggerFromLogr(&cliLogger)), detectOpt) return &Cluster{ provider: provider, httpClient: util.GetHttpClient(), name: name, kindConfigPath: kindConfigPath, kubeVersion: kubeVersion, kubeConfigPath: kubeConfigPath, extraPortsMapping: extraPortsMapping, registryConfig: registryConfig, cfg: cfg, }, nil } func (c *Cluster) Exists() (bool, error) { providerClusters, err := c.provider.List() if err != nil { return false, err } for _, pc := range providerClusters { if pc == c.name { return true, nil } } return false, nil } // getClusterHealthError returns a user-friendly error message for cluster health issues func (c *Cluster) getClusterHealthError(context string) error { return fmt.Errorf(`%s: cluster %s is not healthy. To fix this: 1. Delete the existing cluster: kind delete cluster --name %s 2. Recreate the cluster: idpbuilder create --name %s For more options, run: idpbuilder create --help If the problem persists, check the cluster logs with: kind export logs --name %s `, context, c.name, c.name, c.name, c.name) } // isHealthy checks if the cluster is in a healthy state by attempting to list nodes func (c *Cluster) isHealthy() bool { nodes, err := c.provider.ListNodes(c.name) if err != nil { setupLog.V(1).Info("Failed to list cluster nodes", "cluster", c.name, "error", err) return false } return len(nodes) > 0 } func (c *Cluster) Reconcile(ctx context.Context, recreate bool) error { clusterExists, err := c.Exists() if err != nil { return fmt.Errorf("checking if cluster exists: %w", err) } if clusterExists { if recreate { setupLog.Info("Existing cluster found. Deleting.", "cluster", c.name) err := c.provider.Delete(c.name, "") if err != nil { return fmt.Errorf("deleting cluster: %w", err) } } else { setupLog.Info("Cluster already exists", "cluster", c.name) if !c.isHealthy() { return c.getClusterHealthError("Cluster exists but is not healthy") } return nil } } rawConfig, err := c.getConfig() if err != nil { return err } fmt.Print("########################### Our kind config ############################\n") fmt.Printf("%s", rawConfig) fmt.Print("\n######################### config end ############################\n") setupLog.Info("Creating kind cluster", "cluster", c.name) if err = c.provider.Create( c.name, cluster.CreateWithRawConfig(rawConfig), ); err != nil { t := &kindexec.RunError{} if errors.As(err, &t) { return fmt.Errorf("%w: %s", err, t.Output) } return err } setupLog.Info("Done creating cluster", "cluster", c.name) return nil } func (c *Cluster) ExportKubeConfig(name string, internal bool) error { // Verify cluster is healthy before exporting kubeconfig if !c.isHealthy() { return c.getClusterHealthError("Cannot export kubeconfig") } err := c.provider.ExportKubeConfig(name, c.kubeConfigPath, internal) if err != nil { return fmt.Errorf("%w\n%w", err, c.getClusterHealthError("Failed to export kubeconfig")) } return nil } func (c *Cluster) ensureCorrectConfig(in []byte) (kindv1alpha4.Cluster, error) { // see pkg/kind/resources/kind.yaml.tmpl and pkg/controllers/localbuild/resources/nginx/k8s/ingress-nginx.yaml // defines which container port we should be looking for. containerPort := "443" if c.cfg.Protocol == "http" { containerPort = "80" } parsedCluster := kindv1alpha4.Cluster{} err := yaml.Unmarshal(in, &parsedCluster) if err != nil { return kindv1alpha4.Cluster{}, fmt.Errorf("parsing kind config: %w", err) } // the port and ingress-nginx label must be on the same node to ensure nginx runs on the node with the right port. appendNecessaryPort := true appendIngressNodeLabel := true // pick the first node for the ingress-nginx if we need to configure node port. nodePosition := 0 if parsedCluster.Nodes == nil || len(parsedCluster.Nodes) == 0 { return kindv1alpha4.Cluster{}, fmt.Errorf("provided kind config does not have the node field defined") } nodes: for i := range parsedCluster.Nodes { node := parsedCluster.Nodes[i] for _, pm := range node.ExtraPortMappings { if strconv.Itoa(int(pm.HostPort)) == c.cfg.Port { appendNecessaryPort = false nodePosition = i if node.Labels != nil { v, ok := node.Labels[ingressNginxNodeLabelKey] if ok && v == ingressNginxNodeLabelValue { appendIngressNodeLabel = false } } break nodes } } if node.Labels != nil { v, ok := node.Labels[ingressNginxNodeLabelKey] if ok && v == ingressNginxNodeLabelValue { appendIngressNodeLabel = false nodePosition = i break nodes } } } if appendNecessaryPort { hp, err := strconv.Atoi(c.cfg.Port) if err != nil { return kindv1alpha4.Cluster{}, fmt.Errorf("converting port, %s, to int: %w", c.cfg.Port, err) } // either "80" or "443". No need to check for err cp, _ := strconv.Atoi(containerPort) if parsedCluster.Nodes[nodePosition].ExtraPortMappings == nil { parsedCluster.Nodes[nodePosition].ExtraPortMappings = make([]kindv1alpha4.PortMapping, 0, 1) } parsedCluster.Nodes[nodePosition].ExtraPortMappings = append(parsedCluster.Nodes[nodePosition].ExtraPortMappings, kindv1alpha4.PortMapping{ContainerPort: int32(cp), HostPort: int32(hp), Protocol: "TCP"}) } if appendIngressNodeLabel { if parsedCluster.Nodes[nodePosition].Labels == nil { parsedCluster.Nodes[nodePosition].Labels = make(map[string]string) } parsedCluster.Nodes[nodePosition].Labels[ingressNginxNodeLabelKey] = ingressNginxNodeLabelValue } return parsedCluster, nil } ================================================ FILE: pkg/kind/cluster_test.go ================================================ package kind import ( "context" "io" "os" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/go-logr/logr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "regexp" "sigs.k8s.io/kind/pkg/cluster/nodes" "sigs.k8s.io/kind/pkg/exec" ) func TestGetConfig(t *testing.T) { type tc struct { host string port string registryConfig []string usePathRouting bool expectConfig string } tcs := []tc{ { host: "cnoe.localtest.me", port: "8443", registryConfig: []string{}, usePathRouting: false, expectConfig: `kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane image: "kindest/node:v1.26.3" labels: ingress-ready: "true" extraPortMappings: - containerPort: 443 hostPort: 8443 protocol: TCP - containerPort: 32222 hostPort: 32222 protocol: TCP extraMounts: - containerPath: /etc/containerd/certs.d hostPath: /tmp/idpbuilder-registry-certs.d-\d+ containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d"`, }, { host: "cnoe.localtest.me", port: "8443", registryConfig: []string{"testdata/doesnt-exist.json", "testdata/empty.json"}, usePathRouting: true, expectConfig: `kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane image: "kindest/node:v1.26.3" labels: ingress-ready: "true" extraPortMappings: - containerPort: 443 hostPort: 8443 protocol: TCP - containerPort: 32222 hostPort: 32222 protocol: TCP extraMounts: - containerPath: /etc/containerd/certs.d hostPath: /tmp/idpbuilder-registry-certs.d-\d+ - containerPath: /var/lib/kubelet/config.json hostPath: testdata/empty.json containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d"`, }, } for i := range tcs { c := tcs[i] cluster, err := NewCluster("testcase", "v1.26.3", "", "", "", c.registryConfig, v1alpha1.BuildCustomizationSpec{ Host: c.host, Port: c.port, UsePathRouting: c.usePathRouting, }, logr.Discard()) assert.NoError(t, err) cfg, err := cluster.getConfig() assert.NoError(t, err) re := regexp.MustCompile("(?m)" + c.expectConfig) assert.Regexp(t, re, string(cfg), "config did not match expected config regexp") } } func TestExtraPortMappings(t *testing.T) { cluster, err := NewCluster("testcase", "v1.26.3", "", "", "22:32222", nil, v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", }, logr.Discard()) if err != nil { t.Fatalf("Initializing cluster resource: %v", err) } cfg, err := cluster.getConfig() if err != nil { t.Errorf("Error getting kind config: %v", err) } expectConfig := `kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane image: "kindest/node:v1.26.3" labels: ingress-ready: "true" extraPortMappings: - containerPort: 443 hostPort: 8443 protocol: TCP - containerPort: 32222 hostPort: 32222 protocol: TCP - containerPort: 32222 hostPort: 22 protocol: TCP extraMounts: - containerPath: /etc/containerd/certs.d hostPath: /tmp/idpbuilder-registry-certs.d-\d+ containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d"` re := regexp.MustCompile("(?m)" + expectConfig) assert.Regexp(t, re, string(cfg), "config did not match expected config regexp") } func TestGetConfigCustom(t *testing.T) { type testCase struct { inputPath string outputPath string hostPort string protocol string error bool } cases := []testCase{ { inputPath: "testdata/no-port.yaml", outputPath: "testdata/expected/no-port.yaml", hostPort: "8443", protocol: "https", }, { inputPath: "testdata/port-only.yaml", outputPath: "testdata/expected/port-only.yaml", hostPort: "80", protocol: "http", }, { inputPath: "testdata/no-port-multi.yaml", outputPath: "testdata/expected/no-port-multi.yaml", hostPort: "8443", protocol: "https", }, { inputPath: "testdata/label-only.yaml", outputPath: "testdata/expected/label-only.yaml", hostPort: "8443", protocol: "https", }, { inputPath: "testdata/no-node", error: true, }, } for _, v := range cases { c, _ := NewCluster("testcase", "v1.26.3", "", v.inputPath, "", nil, v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: v.hostPort, Protocol: v.protocol, }, logr.Discard()) b, err := c.getConfig() if v.error { assert.Error(t, err) continue } assert.NoError(t, err) expected, _ := os.ReadFile(v.outputPath) assert.YAMLEq(t, string(expected), string(b)) } } // Mock provider for testing type mockProvider struct { mock.Mock IProvider } func (m *mockProvider) ListNodes(name string) ([]nodes.Node, error) { args := m.Called(name) return args.Get(0).([]nodes.Node), args.Error(1) } type mockRuntime struct { mock.Mock } func (m *mockRuntime) ContainerWithPort(ctx context.Context, name string, port string) (bool, error) { args := m.Called(ctx, name, port) return args.Get(0).(bool), args.Error(1) } // Mock Docker client for testing type DockerClientMock struct { client.APIClient mock.Mock } func (m *DockerClientMock) ContainerList(ctx context.Context, listOptions types.ContainerListOptions) ([]types.Container, error) { mockArgs := m.Called(ctx, listOptions) return mockArgs.Get(0).([]types.Container), mockArgs.Error(1) } type NodeMock struct { mock.Mock } func (n *NodeMock) Command(command string, args ...string) exec.Cmd { argsMock := append([]string{command}, args...) mockArgs := n.Called(argsMock) return mockArgs.Get(0).(exec.Cmd) } func (n *NodeMock) String() string { args := n.Called() return args.String(0) } func (n *NodeMock) Role() (string, error) { args := n.Called() return args.String(0), args.Error(1) } func (n *NodeMock) IP() (ipv4 string, ipv6 string, err error) { args := n.Called() return args.String(0), args.String(1), args.Error(2) } func (n *NodeMock) SerialLogs(writer io.Writer) error { args := n.Called(writer) return args.Error(0) } func (n *NodeMock) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { mockArgs := n.Called(nil) return mockArgs.Get(0).(exec.Cmd) } ================================================ FILE: pkg/kind/config.go ================================================ package kind import ( "embed" "fmt" "io" "io/fs" "os" "path/filepath" "strings" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/util/files" ) type PortMapping struct { HostPort string ContainerPort string } type TemplateConfig struct { v1alpha1.BuildCustomizationSpec KubernetesVersion string ExtraPortsMapping []PortMapping RegistryConfig string RegistryCertsDir string } //go:embed resources/* testdata/custom-kind.yaml.tmpl var configFS embed.FS func loadConfig(path string, httpClient HttpClient) ([]byte, error) { var rawConfigTempl []byte var err error if path != "" { if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") { resp, err := httpClient.Get(path) if err != nil { return nil, fmt.Errorf("fetching remote kind config: %w", err) } defer resp.Body.Close() if !(resp.StatusCode < 300 && resp.StatusCode >= 200) { return nil, fmt.Errorf("got %d status code when fetching kind config", resp.StatusCode) } rawConfigTempl, err = io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("reading remote kind config body: %w", err) } } else { rawConfigTempl, err = os.ReadFile(path) } } else { rawConfigTempl, err = fs.ReadFile(configFS, "resources/kind.yaml.tmpl") } if err != nil { return nil, fmt.Errorf("reading kind config: %w", err) } return rawConfigTempl, nil } func parsePortMappings(extraPortsMapping string) []PortMapping { var portMappingPairs []PortMapping if len(extraPortsMapping) > 0 { // Split pairs of ports "11=1111","22=2222",etc pairs := strings.Split(extraPortsMapping, ",") // Create a slice to store PortMapping pairs. portMappingPairs = make([]PortMapping, len(pairs)) // Parse each pair into PortPair objects. for i, pair := range pairs { parts := strings.Split(pair, ":") if len(parts) == 2 { portMappingPairs[i] = PortMapping{parts[0], parts[1]} } } } return portMappingPairs } func findRegistryConfig(registryConfigPaths []string) string { for _, s := range registryConfigPaths { path := os.ExpandEnv(s) if _, err := os.Stat(path); err == nil { return path } } return "" } func renderRegistryCertsDir(cfg v1alpha1.BuildCustomizationSpec) (string, error) { // Generate the directory structure dir, err := os.MkdirTemp("", "idpbuilder-registry-certs.d-*") if err != nil { return "", fmt.Errorf("creating temp dir %w", err) } var hostAndPort string if cfg.UsePathRouting { hostAndPort = fmt.Sprintf("%s:%s", cfg.Host, cfg.Port) } else { hostAndPort = fmt.Sprintf("gitea.%s:%s", cfg.Host, cfg.Port) } hostCertsDir := filepath.Join(dir, hostAndPort) err = os.Mkdir(hostCertsDir, 0700) if err != nil { return "", fmt.Errorf("creating temp dir for host %w", err) } // Render out the template rawConfigTempl, err := fs.ReadFile(configFS, "resources/hosts.toml.tmpl") if err != nil { return "", fmt.Errorf("reading insecure registry config %w", err) } var retBuff []byte if retBuff, err = files.ApplyTemplate(rawConfigTempl, cfg); err != nil { return "", fmt.Errorf("templating insecure registry config %w", err) } hostsFile := filepath.Join(hostCertsDir, "hosts.toml") err = os.WriteFile(hostsFile, retBuff, 0700) if err != nil { return "", fmt.Errorf("writing insecure registry config %w", err) } // Render and write hosts.toml for each registry mirror for _, mirror := range cfg.RegistryMirrors { mirrorCertsDir := filepath.Join(dir, mirror.TargetRegistry) err = os.Mkdir(mirrorCertsDir, 0700) if err != nil { return "", fmt.Errorf("creating temp dir for mirror %w", err) } // Render out the mirror template rawMirrorTempl, err := fs.ReadFile(configFS, "resources/hosts-mirror.toml.tmpl") if err != nil { return "", fmt.Errorf("reading registry mirror config %w", err) } mirrorData := struct { RegistryAddress string InsecureRegistryMirrors bool }{ RegistryAddress: mirror.RegistryAddress, InsecureRegistryMirrors: cfg.InsecureRegistryMirrors, } var retBuff []byte if retBuff, err = files.ApplyTemplate(rawMirrorTempl, mirrorData); err != nil { return "", fmt.Errorf("templating registry mirror config %w", err) } hostsFile := filepath.Join(mirrorCertsDir, "hosts.toml") err = os.WriteFile(hostsFile, retBuff, 0700) if err != nil { return "", fmt.Errorf("writing registry mirror config %w", err) } } return dir, nil } ================================================ FILE: pkg/kind/config_integration_test.go ================================================ package kind import ( "os" "path/filepath" "strings" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" ) func TestRegistryMirrorHostsTomlContent(t *testing.T) { // Test that the generated hosts.toml for mirrors has the correct content cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", InsecureRegistryMirrors: true, RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Check docker.io hosts.toml content dockerHostsFile := filepath.Join(dir, "docker.io", "hosts.toml") content, err := os.ReadFile(dockerHostsFile) if err != nil { t.Fatalf("failed to read hosts.toml: %v", err) } contentStr := string(content) // Verify key content exists expectedContent := []string{ `server = "http://kind-registry:5000"`, `skip_verify = true`, `[host."http://kind-registry:5000"]`, `capabilities = ["pull", "resolve"]`, } for _, expected := range expectedContent { if !strings.Contains(contentStr, expected) { t.Errorf("hosts.toml missing expected content: %s\nActual content:\n%s", expected, contentStr) } } // Verify content that should NOT exist unexpectedContent := []string{ `proxy`, `https://docker.io`, // Should not reference target registry directly } for _, unexpected := range unexpectedContent { if strings.Contains(contentStr, unexpected) { t.Errorf("hosts.toml should not contain: %s\nActual content:\n%s", unexpected, contentStr) } } } func TestMultipleMirrors(t *testing.T) { // Test with multiple mirrors pointing to different registries cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, { TargetRegistry: "ghcr.io", RegistryAddress: "http://kind-registry:5000", }, { TargetRegistry: "quay.io", RegistryAddress: "https://my-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Verify all mirror directories exist registries := []string{"docker.io", "ghcr.io", "quay.io"} for _, registry := range registries { mirrorDir := filepath.Join(dir, registry) if _, err := os.Stat(mirrorDir); os.IsNotExist(err) { t.Errorf("expected mirror directory %s does not exist", mirrorDir) } hostsFile := filepath.Join(mirrorDir, "hosts.toml") if _, err := os.Stat(hostsFile); os.IsNotExist(err) { t.Errorf("expected hosts.toml file %s does not exist", hostsFile) } } // Verify docker.io uses http dockerFile := filepath.Join(dir, "docker.io", "hosts.toml") content, _ := os.ReadFile(dockerFile) if !strings.Contains(string(content), `server = "http://kind-registry:5000"`) { t.Errorf("docker.io should have http server URL") } // Verify quay.io uses https (since RegistryAddress starts with https) quayFile := filepath.Join(dir, "quay.io", "hosts.toml") content, _ = os.ReadFile(quayFile) if !strings.Contains(string(content), `server = "https://my-registry:5000"`) { t.Errorf("quay.io should have https server URL") } } func TestMirrorWithExistingGiteaConfig(t *testing.T) { // Test that mirrors work alongside the existing gitea registry config cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Verify gitea config exists giteaDir := filepath.Join(dir, "gitea.cnoe.localtest.me:8443") if _, err := os.Stat(giteaDir); os.IsNotExist(err) { t.Errorf("expected gitea directory %s does not exist", giteaDir) } giteaHostsFile := filepath.Join(giteaDir, "hosts.toml") if _, err := os.Stat(giteaHostsFile); os.IsNotExist(err) { t.Errorf("expected gitea hosts.toml file %s does not exist", giteaHostsFile) } // Verify docker.io mirror exists dockerDir := filepath.Join(dir, "docker.io") if _, err := os.Stat(dockerDir); os.IsNotExist(err) { t.Errorf("expected docker.io directory %s does not exist", dockerDir) } dockerHostsFile := filepath.Join(dockerDir, "hosts.toml") if _, err := os.Stat(dockerHostsFile); os.IsNotExist(err) { t.Errorf("expected docker.io hosts.toml file %s does not exist", dockerHostsFile) } } func TestMirrorWithHTTPS(t *testing.T) { // Test that mirrors work with HTTPS addresses cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "https://secure-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Check docker.io hosts.toml content dockerHostsFile := filepath.Join(dir, "docker.io", "hosts.toml") content, err := os.ReadFile(dockerHostsFile) if err != nil { t.Fatalf("failed to read hosts.toml: %v", err) } contentStr := string(content) // Verify https is used if !strings.Contains(contentStr, `server = "https://secure-registry:5000"`) { t.Errorf("hosts.toml should contain https server URL\nActual content:\n%s", contentStr) } if !strings.Contains(contentStr, `[host."https://secure-registry:5000"]`) { t.Errorf("hosts.toml should contain https host configuration\nActual content:\n%s", contentStr) } } func TestMirrorWithHTTP(t *testing.T) { // Test that mirrors work with HTTP addresses cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://insecure-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Check docker.io hosts.toml content dockerHostsFile := filepath.Join(dir, "docker.io", "hosts.toml") content, err := os.ReadFile(dockerHostsFile) if err != nil { t.Fatalf("failed to read hosts.toml: %v", err) } contentStr := string(content) // Verify http is used if !strings.Contains(contentStr, `server = "http://insecure-registry:5000"`) { t.Errorf("hosts.toml should contain http server URL\nActual content:\n%s", contentStr) } if !strings.Contains(contentStr, `[host."http://insecure-registry:5000"]`) { t.Errorf("hosts.toml should contain http host configuration\nActual content:\n%s", contentStr) } if strings.Contains(contentStr, `skip_verify = true`) { t.Errorf("hosts.toml should not contain skip_verify unless insecure-registry-mirrors is set\nActual content:\n%s", contentStr) } } func TestMirrorWithHTTPInsecure(t *testing.T) { cfg := v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", InsecureRegistryMirrors: true, RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://insecure-registry:5000", }, }, } dir, err := renderRegistryCertsDir(cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) dockerHostsFile := filepath.Join(dir, "docker.io", "hosts.toml") content, err := os.ReadFile(dockerHostsFile) if err != nil { t.Fatalf("failed to read hosts.toml: %v", err) } contentStr := string(content) if !strings.Contains(contentStr, `skip_verify = true`) { t.Errorf("hosts.toml should contain skip_verify when insecure-registry-mirrors is set\nActual content:\n%s", contentStr) } } ================================================ FILE: pkg/kind/config_test.go ================================================ package kind import ( "errors" "io" "io/fs" "net/http" "os" "path/filepath" "reflect" "strings" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" ) type MockHttpClient struct{} func (o *MockHttpClient) Get(url string) (resp *http.Response, err error) { if url == "https://doesnotexist" || url == "http://doesnotexist" { return nil, errors.New("connection error") } else if url == "https://404" { body := io.NopCloser(strings.NewReader("")) r := http.Response{ Status: "404 NotFound", StatusCode: 404, Body: body, } return &r, nil } body := io.NopCloser(strings.NewReader("foo: bar")) r := http.Response{ Status: "200 OK", StatusCode: 200, Body: body, } return &r, nil } func TestLoadConfig(t *testing.T) { httpClient := MockHttpClient{} defaultTemplate, err := fs.ReadFile(configFS, "resources/kind.yaml.tmpl") if err != nil { t.Fatalf("failed to load default kind template: %v", err) } customTemplate, err := fs.ReadFile(configFS, "testdata/custom-kind.yaml.tmpl") if err != nil { t.Fatalf("failed to load custom kind template: %v", err) } httpsTemplate := []byte("foo: bar") connectionErr := "fetching remote kind config: connection error" notFoundErr := "got 404 status code when fetching kind config" type test struct { path string expected []byte err *string } tests := []test{ { path: "", expected: defaultTemplate, err: nil, }, { path: "testdata/custom-kind.yaml.tmpl", expected: customTemplate, err: nil, }, { path: "https://doesnotexist", expected: defaultTemplate, err: &connectionErr, }, { path: "http://doesnotexist", expected: customTemplate, err: &connectionErr, }, { path: "https://404", expected: defaultTemplate, err: ¬FoundErr, }, { path: "https://anyurlworks", expected: httpsTemplate, err: nil, }, } for _, tc := range tests { out, err := loadConfig(tc.path, &httpClient) if tc.err != nil { if err != nil { if err.Error() != *tc.err { t.Errorf("expected error: %v\nfound error: %v", *tc.err, err.Error()) } } else { t.Errorf("expected error: %v\ndidnt find an error", *tc.err) } } else { if err != nil { t.Errorf("failed to load kind config: %v", err) } if !reflect.DeepEqual(tc.expected, out) { t.Errorf("expected:\n%v\ngot:\n%v", string(tc.expected), string(out)) } } } } func TestExtraPortMappingsUtilFunc(t *testing.T) { type test struct { extraPortMappings string expected []PortMapping } tests := []test{ { extraPortMappings: "", expected: []PortMapping(nil), }, { extraPortMappings: "22:32222", expected: []PortMapping{ { HostPort: "22", ContainerPort: "32222", }, }, }, { extraPortMappings: "11:1111,33:3333,4444:4444", expected: []PortMapping{ { HostPort: "11", ContainerPort: "1111", }, { HostPort: "33", ContainerPort: "3333", }, { HostPort: "4444", ContainerPort: "4444", }, }, }, } for _, tc := range tests { pmOutput := parsePortMappings(tc.extraPortMappings) if !reflect.DeepEqual(tc.expected, pmOutput) { t.Errorf("expected: %v, got: %v", tc.expected, pmOutput) } } } func TestFindRegistryConfig(t *testing.T) { type test struct { paths []string expected string } tests := []test{ { paths: []string{"testdata/empty.json"}, expected: "testdata/empty.json", }, { paths: []string{"doesntexist"}, expected: "", }, { paths: []string{"doesntexist", "testdata/empty.json"}, expected: "testdata/empty.json", }, } for _, tc := range tests { out := findRegistryConfig(tc.paths) if !reflect.DeepEqual(tc.expected, out) { t.Errorf("expected:\n%v\ngot:\n%v", tc.expected, out) } } } func TestRenderRegistryCertsDirWithMirrors(t *testing.T) { type test struct { name string cfg v1alpha1.BuildCustomizationSpec expectedDirs []string expectedFileCount int expectSkipVerify bool } tests := []test{ { name: "no mirrors", cfg: v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", }, expectedDirs: []string{"gitea.cnoe.localtest.me:8443"}, expectedFileCount: 1, }, { name: "with single mirror", cfg: v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, }, expectedDirs: []string{"gitea.cnoe.localtest.me:8443", "docker.io"}, expectedFileCount: 2, }, { name: "with mirrors and insecure skip verify", cfg: v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", InsecureRegistryMirrors: true, RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, }, }, expectedDirs: []string{"gitea.cnoe.localtest.me:8443", "docker.io"}, expectedFileCount: 2, expectSkipVerify: true, }, { name: "with multiple mirrors", cfg: v1alpha1.BuildCustomizationSpec{ Host: "cnoe.localtest.me", Port: "8443", RegistryMirrors: []v1alpha1.RegistryMirror{ { TargetRegistry: "docker.io", RegistryAddress: "http://kind-registry:5000", }, { TargetRegistry: "ghcr.io", RegistryAddress: "http://kind-registry:5000", }, }, }, expectedDirs: []string{"gitea.cnoe.localtest.me:8443", "docker.io", "ghcr.io"}, expectedFileCount: 3, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { dir, err := renderRegistryCertsDir(tc.cfg) if err != nil { t.Fatalf("failed to render registry certs dir: %v", err) } defer os.RemoveAll(dir) // Check all expected directories exist for _, expectedDir := range tc.expectedDirs { fullPath := filepath.Join(dir, expectedDir) if _, err := os.Stat(fullPath); os.IsNotExist(err) { t.Errorf("expected directory %s does not exist", fullPath) } // Check hosts.toml exists in each directory hostsFile := filepath.Join(fullPath, "hosts.toml") if _, err := os.Stat(hostsFile); os.IsNotExist(err) { t.Errorf("expected hosts.toml file %s does not exist", hostsFile) } // For mirrors, check the content if expectedDir != "gitea.cnoe.localtest.me:8443" { content, err := os.ReadFile(hostsFile) if err != nil { t.Fatalf("failed to read hosts.toml: %v", err) } contentStr := string(content) if tc.expectSkipVerify { if !strings.Contains(contentStr, "skip_verify = true") { t.Errorf("hosts.toml for mirror %s should contain skip_verify = true", expectedDir) } } else if strings.Contains(contentStr, "skip_verify = true") { t.Errorf("hosts.toml for mirror %s should not contain skip_verify = true", expectedDir) } if !strings.Contains(contentStr, "[host.") { t.Errorf("hosts.toml for mirror %s should contain host configuration", expectedDir) } } } }) } } ================================================ FILE: pkg/kind/kindlogger.go ================================================ package kind import ( "fmt" "github.com/go-logr/logr" kindlog "sigs.k8s.io/kind/pkg/log" ) // this is a wrapper of logr.Logger made specifically for kind' logger. // this is needed because kind's implementation is internal. // https://github.com/kubernetes-sigs/kind/blob/1a8f0473a0785e0975e26739524513e8ee696be3/pkg/log/types.go type kindLogger struct { cliLogger *logr.Logger } func (l *kindLogger) Warn(message string) { l.cliLogger.Info(message) } func (l *kindLogger) Warnf(message string, args ...interface{}) { l.cliLogger.Info(fmt.Sprintf(message, args...)) } func (l *kindLogger) Error(message string) { l.cliLogger.Error(fmt.Errorf(message), "") } func (l *kindLogger) Errorf(message string, args ...interface{}) { msg := fmt.Sprintf(message, args...) l.cliLogger.Error(fmt.Errorf(msg), "") } func (l *kindLogger) V(level kindlog.Level) kindlog.InfoLogger { return newKindInfoLogger(l.cliLogger, int(level)) } // KindLoggerFromLogr is a wrapper of logr.Logger made specifically for kind's InfoLogger. // https://github.com/kubernetes-sigs/kind/blob/1a8f0473a0785e0975e26739524513e8ee696be3/pkg/log/types.go func KindLoggerFromLogr(logrLogger *logr.Logger) *kindLogger { return &kindLogger{ cliLogger: logrLogger, } } func newKindInfoLogger(logrLogger *logr.Logger, level int) *kindInfoLogger { return &kindInfoLogger{ cliLogger: logrLogger, level: level + 1, // push log level down. e.g. info log becomes debug+1. } } type kindInfoLogger struct { cliLogger *logr.Logger level int } func (k *kindInfoLogger) Info(message string) { k.cliLogger.V(k.level).Info(message) } func (k *kindInfoLogger) Infof(message string, args ...interface{}) { k.cliLogger.V(k.level).Info(fmt.Sprintf(message, args...)) } func (k *kindInfoLogger) Enabled() bool { return k.cliLogger.Enabled() } ================================================ FILE: pkg/kind/resources/hosts-mirror.toml.tmpl ================================================ server = "{{ .RegistryAddress }}" [host."{{ .RegistryAddress }}"] capabilities = ["pull", "resolve"] {{- if .InsecureRegistryMirrors }} skip_verify = true {{- end }} ================================================ FILE: pkg/kind/resources/hosts.toml.tmpl ================================================ {{ if .UsePathRouting -}} server = "https://{{ .Host }}:{{ .Port }}" [host."https://{{ .Host }}"] capabilities = ["pull", "resolve"] skip_verify = true {{ else -}} server = "https://gitea.{{ .Host }}:{{ .Port }}" [host."https://gitea.{{ .Host }}"] capabilities = ["pull", "resolve"] skip_verify = true {{ end -}} ================================================ FILE: pkg/kind/resources/kind.yaml.tmpl ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane image: "kindest/node:{{ .KubernetesVersion }}" labels: ingress-ready: "true" extraPortMappings: - containerPort: {{ if (eq .Protocol "http") -}} 80 {{- else -}} 443 {{- end }} hostPort: {{ .Port }} {{- if .StaticPassword }} listenAddress: "127.0.0.1" {{- end }} protocol: TCP - containerPort: 32222 hostPort: 32222 protocol: TCP {{- range .ExtraPortsMapping }} - containerPort: {{ .ContainerPort }} hostPort: {{ .HostPort }} protocol: TCP {{- end }} extraMounts: - containerPath: /etc/containerd/certs.d hostPath: {{ .RegistryCertsDir }} {{- if .RegistryConfig }} - containerPath: /var/lib/kubelet/config.json hostPath: {{ .RegistryConfig }} {{- end }} containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d" ================================================ FILE: pkg/kind/testdata/custom-kind.yaml.tmpl ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane image: "kindest/node:{{ .KubernetesVersion }}" labels: ingress-ready: "true" extraPortMappings: - containerPort: {{ if (eq .Protocol "http") -}} 80 {{- else -}} 443 {{- end }} hostPort: {{ .Port }} protocol: TCP - containerPort: 10 hostPort: 1000 protocol: TCP {{ range .ExtraPortsMapping -}} - containerPort: {{ .ContainerPort }} hostPort: {{ .HostPort }} protocol: TCP {{ end }} containerdConfigPatches: - |- {{ if .UsePathRouting -}} [plugins."io.containerd.grpc.v1.cri".registry.mirrors."{{ .Host }}:{{ .Port }}"] endpoint = ["https://{{ .Host }}"] [plugins."io.containerd.grpc.v1.cri".registry.configs."{{ .Host }}".tls] insecure_skip_verify = true {{- else -}} [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gitea.{{ .Host }}:{{ .Port }}"] endpoint = ["https://gitea.{{ .Host }}"] [plugins."io.containerd.grpc.v1.cri".registry.configs."gitea.{{ .Host }}".tls] insecure_skip_verify = true {{- end -}} ================================================ FILE: pkg/kind/testdata/empty.json ================================================ ================================================ FILE: pkg/kind/testdata/expected/label-only.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: {} nodes: - role: control-plane extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - role: worker image: "abc" labels: ingress-ready: "true" extraPortMappings: - containerPort: 443 hostPort: 8443 protocol: TCP ================================================ FILE: pkg/kind/testdata/expected/no-port-multi.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: {} nodes: - role: control-plane labels: ingress-ready: "true" extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - containerPort: 443 hostPort: 8443 protocol: TCP - role: worker image: "abc" ================================================ FILE: pkg/kind/testdata/expected/no-port.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: {} nodes: - role: control-plane labels: ingress-ready: "true" extraMounts: - containerPath: /var/lib/kubelet/config.json hostPath: ~/.docker/config.json extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - containerPort: 443 hostPort: 8443 protocol: TCP ================================================ FILE: pkg/kind/testdata/expected/port-only.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: {} nodes: - role: control-plane extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - role: worker labels: ingress-ready: "true" extraPortMappings: - containerPort: 80 hostPort: 80 protocol: TCP ================================================ FILE: pkg/kind/testdata/label-only.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - role: worker image: "abc" labels: ingress-ready: "true" ================================================ FILE: pkg/kind/testdata/no-node.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 ================================================ FILE: pkg/kind/testdata/no-port-multi.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - role: worker image: "abc" ================================================ FILE: pkg/kind/testdata/no-port.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraMounts: - containerPath: /var/lib/kubelet/config.json hostPath: ~/.docker/config.json extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 ================================================ FILE: pkg/kind/testdata/port-only.yaml ================================================ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 31337 hostPort: 31337 - containerPort: 31340 hostPort: 31340 - containerPort: 31333 hostPort: 31333 - role: worker extraPortMappings: - containerPort: 80 hostPort: 80 protocol: TCP ================================================ FILE: pkg/logger/handler.go ================================================ package logger import ( "context" "fmt" "io" "log/slog" "runtime" "slices" "sync" "time" ) // https://en.wikipedia.org/wiki/ANSI_escape_code const ( Reset = "\033[0m" White = "\033[37m" WhiteDim = "\033[37;2m" Green = "\033[32m" GreenDimUnderlined = "\033[32;2;4m" Magenta = "\033[35m" BrightRed = "\033[91m" BrightYellow = "\033[93m" Cyan = "\033[36m" CyanDim = "\033[36;2m" // this mirrors the limit value from the internal slog package maxBufferSize = 16384 dateFormat = time.Stamp ) var bufPool = sync.Pool{ New: func() any { b := make([]byte, 0, 2048) return &b }, } type Options struct { AddSource bool Colored bool Level slog.Leveler TimeFormat string } // Handler is very similar to slog's commonHandler type Handler struct { opts Options json bool preformattedAttrs []byte groupPrefix string groups []string unopenedGroups []string nOpenGroups int mu *sync.Mutex w io.Writer } func NewHandler(out io.Writer, opts Options) *Handler { return &Handler{ opts: opts, preformattedAttrs: make([]byte, 0), unopenedGroups: make([]string, 0), nOpenGroups: 0, mu: &sync.Mutex{}, w: out, } } func (h *Handler) clone() *Handler { return &Handler{ opts: h.opts, json: h.json, preformattedAttrs: slices.Clip(h.preformattedAttrs), groupPrefix: h.groupPrefix, groups: slices.Clip(h.groups), nOpenGroups: h.nOpenGroups, w: h.w, mu: h.mu, } } func (h *Handler) Enabled(_ context.Context, level slog.Level) bool { minLevel := slog.LevelInfo if h.opts.Level != nil { minLevel = h.opts.Level.Level() } return level >= minLevel } func (h *Handler) WithGroup(name string) slog.Handler { if name == "" { return h } h2 := h.clone() h2.unopenedGroups = make([]string, len(h.unopenedGroups)+1) copy(h2.unopenedGroups, h.unopenedGroups) h2.unopenedGroups[len(h2.unopenedGroups)-1] = name return h2 } func (h *Handler) WithAttrs(as []slog.Attr) slog.Handler { if len(as) == 0 { return h } h2 := h.clone() h2.preformattedAttrs = h2.appendUnopenedGroups(h2.preformattedAttrs) h2.unopenedGroups = nil for _, a := range as { h2.preformattedAttrs = h2.appendAttr(h2.preformattedAttrs, a) } return h2 } func (h *Handler) appendUnopenedGroups(buf []byte) []byte { for _, g := range h.unopenedGroups { buf = fmt.Appendf(buf, "%s ", g) } return buf } func (h *Handler) appendAttr(buf []byte, a slog.Attr) []byte { a.Value = a.Value.Resolve() if a.Equal(slog.Attr{}) { return buf } switch a.Value.Kind() { case slog.KindGroup: attrs := a.Value.Group() if len(attrs) == 0 { return buf } if a.Key != "" { for _, ga := range attrs { buf = h.appendAttr(buf, ga) } } default: if a.Key == "" || a.Value.String() == "" { return buf } buf = h.appendKeyValuePair(buf, a) } return buf } func (h *Handler) Handle(ctx context.Context, record slog.Record) error { bufp := bufPool.Get().(*[]byte) buf := *bufp defer func() { *bufp = buf free(bufp) }() // append time, level, then message. if h.opts.Colored { buf = fmt.Appendf(buf, WhiteDim) buf = slog.Time(slog.TimeKey, record.Time).Value.Time().AppendFormat(buf, fmt.Sprintf("%s%s ", dateFormat, Reset)) var color string switch record.Level { case slog.LevelDebug: color = Magenta case slog.LevelInfo: color = Green case slog.LevelWarn: color = BrightYellow case slog.LevelError: color = BrightRed default: color = Magenta } buf = fmt.Appendf(buf, "%s%s%s ", color, record.Level.String(), Reset) buf = fmt.Appendf(buf, "%s%s%s ", Cyan, record.Message, Reset) } else { buf = slog.Time(slog.TimeKey, record.Time).Value.Time().AppendFormat(buf, fmt.Sprintf("%s ", dateFormat)) buf = fmt.Appendf(buf, "%s ", record.Level) buf = fmt.Appendf(buf, "%s ", record.Message) } if h.opts.AddSource { buf = h.appendAttr(buf, slog.Any(slog.SourceKey, source(record))) } buf = append(buf, h.preformattedAttrs...) if record.NumAttrs() > 0 { buf = h.appendUnopenedGroups(buf) record.Attrs(func(a slog.Attr) bool { buf = h.appendAttr(buf, a) return true }) } buf = append(buf, "\n"...) h.mu.Lock() defer h.mu.Unlock() _, err := h.w.Write(buf) return err } func (h *Handler) appendKeyValuePair(buf []byte, a slog.Attr) []byte { if h.opts.Colored { if a.Key == "err" { return fmt.Appendf(buf, "%s%s=%v%s ", BrightRed, a.Key, a.Value.String(), Reset) } return fmt.Appendf(buf, "%s%s=%s%s%s%s ", WhiteDim, a.Key, Reset, White, a.Value.String(), Reset) } return fmt.Appendf(buf, "%s=%v ", a.Key, a.Value.String()) } func free(b *[]byte) { if cap(*b) <= maxBufferSize { *b = (*b)[:0] bufPool.Put(b) } } func source(r slog.Record) *slog.Source { fs := runtime.CallersFrames([]uintptr{r.PC}) f, _ := fs.Next() return &slog.Source{ Function: f.Function, File: f.File, Line: f.Line, } } ================================================ FILE: pkg/printer/cluster.go ================================================ package printer import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type ClusterPrinter struct { Clusters []types.Cluster OutWriter io.Writer } func (cp ClusterPrinter) PrintOutput(format string) error { switch format { case "json": return PrintDataAsJson(cp.Clusters, cp.OutWriter) case "yaml": return PrintDataAsYaml(cp.Clusters, cp.OutWriter) case "table": return PrintDataAsTable(generateClusterTable(cp.Clusters), cp.OutWriter) default: return fmt.Errorf("output format %s is not supported", format) } } func generateClusterTable(input []types.Cluster) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, {Name: "External-Port", Type: "string"}, {Name: "Kube-Api", Type: "string"}, {Name: "TLS", Type: "string"}, {Name: "Kube-Port", Type: "string"}, {Name: "Nodes", Type: "string"}, } for _, cluster := range input { row := metav1.TableRow{ Cells: []interface{}{ cluster.Name, cluster.ExternalPort, cluster.URLKubeApi, cluster.TlsCheck, cluster.KubePort, generateNodeData(cluster.Nodes), }, } table.Rows = append(table.Rows, row) } return *table } func generateNodeData(nodes []types.Node) string { var result string for i, aNode := range nodes { result += aNode.Name if i < len(nodes)-1 { result += "," } } return result } ================================================ FILE: pkg/printer/package.go ================================================ package printer import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type PackagePrinter struct { Packages []types.Package OutWriter io.Writer } func (pp PackagePrinter) PrintOutput(format string) error { switch format { case "json": return PrintDataAsJson(pp.Packages, pp.OutWriter) case "yaml": return PrintDataAsYaml(pp.Packages, pp.OutWriter) case "table": return PrintDataAsTable(generatePackageTable(pp.Packages), pp.OutWriter) default: return fmt.Errorf("output format %s is not supported", format) } } func generatePackageTable(packagesTable []types.Package) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, {Name: "idp namespace", Type: "string"}, {Name: "Git Repository", Type: "string"}, {Name: "Argocd Url", Type: "string"}, {Name: "Status", Type: "string"}, } for _, p := range packagesTable { row := metav1.TableRow{ Cells: []interface{}{ p.Name, p.Namespace, p.GitRepository, p.ArgocdRepository, p.Status, }, } table.Rows = append(table.Rows, row) } return *table } ================================================ FILE: pkg/printer/printer.go ================================================ package printer import ( "encoding/json" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/printers" "sigs.k8s.io/yaml" ) func PrintDataAsTable(table metav1.Table, outWriter io.Writer) error { printer := printers.NewTablePrinter(printers.PrintOptions{}) return printer.PrintObj(&table, outWriter) } func PrintDataAsJson(data any, outWriter io.Writer) error { enc := json.NewEncoder(outWriter) enc.SetEscapeHTML(false) enc.SetIndent("", " ") return enc.Encode(data) } func PrintDataAsYaml(data any, outWriter io.Writer) error { b, err := yaml.Marshal(data) if err != nil { return err } _, err = outWriter.Write(b) return err } ================================================ FILE: pkg/printer/secret.go ================================================ package printer import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/printer/types" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "strings" ) type SecretPrinter struct { Secrets []types.Secret OutWriter io.Writer } func (sp SecretPrinter) PrintOutput(format string) error { switch format { case "json": return PrintDataAsJson(sp.Secrets, sp.OutWriter) case "yaml": return PrintDataAsYaml(sp.Secrets, sp.OutWriter) case "table": return PrintDataAsTable(generateSecretTable(sp.Secrets), sp.OutWriter) default: return fmt.Errorf("output format %s is not supported", format) } } func generateSecretTable(secretTable []types.Secret) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, {Name: "Namespace", Type: "string"}, {Name: "Username", Type: "string"}, {Name: "Password", Type: "string"}, {Name: "Token", Type: "string"}, {Name: "Data", Type: "string"}, } for _, secret := range secretTable { var dataEntries []string if !secret.IsCore { for key, value := range secret.Data { dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) } } dataString := strings.Join(dataEntries, ", ") row := metav1.TableRow{ Cells: []interface{}{ secret.Name, secret.Namespace, secret.Username, secret.Password, secret.Token, dataString, }, } table.Rows = append(table.Rows, row) } return *table } ================================================ FILE: pkg/printer/types/internal_types.go ================================================ package types // Types used internally to define the objects needed to print data, etc type Allocated struct { Cpu string Memory string } type Capacity struct { Memory float64 Pods int64 Cpu int64 } type Cluster struct { Name string URLKubeApi string KubePort int32 TlsCheck bool ExternalPort int32 Nodes []Node } type Node struct { Name string InternalIP string ExternalIP string Capacity Capacity Allocated Allocated } type Package struct { Name string Namespace string Type string GitRepository string ArgocdRepository string Status string } type Secret struct { IsCore bool Name string `json:"name"` Namespace string `json:"namespace"` Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` Token string `json:"token,omitempty"` Data map[string]string `json:"data,omitempty"` } ================================================ FILE: pkg/resources/localbuild/application.go ================================================ package localbuild import ( argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func SetProjectSpec(project *argov1alpha1.AppProject) { project.Spec.Description = "IDP Builder Project" project.Spec.ClusterResourceWhitelist = []v1.GroupKind{{ Group: "*", Kind: "*", }} project.Spec.NamespaceResourceWhitelist = []v1.GroupKind{{ Group: "*", Kind: "*", }} project.Spec.Destinations = []argov1alpha1.ApplicationDestination{{ Name: "*", Namespace: "*", Server: "*", }} project.Spec.SourceRepos = []string{ "*", } } func SetApplicationSpec(app *argov1alpha1.Application, repoUrl, path, project, dstNS string, targetRevision *string) { headRev := "HEAD" if targetRevision == nil { targetRevision = &headRev } app.Spec.Destination = argov1alpha1.ApplicationDestination{ Server: "https://kubernetes.default.svc", Namespace: dstNS, } app.Spec.Project = project app.Spec.Source = &argov1alpha1.ApplicationSource{ Path: path, RepoURL: repoUrl, TargetRevision: *targetRevision, } app.Spec.SyncPolicy = &argov1alpha1.SyncPolicy{ Automated: &argov1alpha1.SyncPolicyAutomated{ SelfHeal: true, }, SyncOptions: argov1alpha1.SyncOptions{ "CreateNamespace=true", }, } } ================================================ FILE: pkg/util/argocd.go ================================================ package util import ( "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( ArgocdInitialAdminSecretName = "argocd-initial-admin-secret" ArgocdAdminName = "admin" ArgocdNamespace = "argocd" ArgocdURLTempl = "%s://%s%s:%s%s" ) func ArgocdBaseUrl(config v1alpha1.BuildCustomizationSpec) string { if config.UsePathRouting { return fmt.Sprintf(ArgocdURLTempl, config.Protocol, "", config.Host, config.Port, "/argocd") } return fmt.Sprintf(ArgocdURLTempl, config.Protocol, "argocd.", config.Host, config.Port, "") } func ArgocdInitialAdminSecretObject() corev1.Secret { return corev1.Secret{ TypeMeta: metav1.TypeMeta{ Kind: "Secret", APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: ArgocdInitialAdminSecretName, Namespace: ArgocdNamespace, }, } } ================================================ FILE: pkg/util/files/files.go ================================================ package files import ( "bytes" "fmt" "io" "os" "path/filepath" "strings" "text/template" ) func CopyDirectory(scrDir, dest string) error { entries, err := os.ReadDir(scrDir) if err != nil { return err } for _, entry := range entries { sourcePath := filepath.Join(scrDir, entry.Name()) destPath := filepath.Join(dest, entry.Name()) fileInfo, err := os.Stat(sourcePath) if err != nil { return err } switch fileInfo.Mode() & os.ModeType { case os.ModeDir: if err := CreateIfNotExists(destPath, 0755); err != nil { return err } if err := CopyDirectory(sourcePath, destPath); err != nil { return err } case os.ModeSymlink: continue default: if err := Copy(sourcePath, destPath); err != nil { return err } } fInfo, err := entry.Info() if err != nil { return err } if err := os.Chmod(destPath, fInfo.Mode()); err != nil { return err } } return nil } func Copy(srcFile, dstFile string) error { out, err := os.Create(dstFile) if err != nil { return err } defer out.Close() in, err := os.Open(srcFile) if err != nil { return err } defer in.Close() _, err = io.Copy(out, in) if err != nil { return err } return nil } func Exists(filePath string) bool { if _, err := os.Stat(filePath); os.IsNotExist(err) { return false } return true } func CreateIfNotExists(dir string, perm os.FileMode) error { if Exists(dir) { return nil } if err := os.MkdirAll(dir, perm); err != nil { return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error()) } return nil } func ApplyTemplate(in []byte, templateData any) ([]byte, error) { funcMap := template.FuncMap{ "indentNewLines": templateIndentNewlines, } t, err := template.New("template").Funcs(funcMap).Parse(string(in)) if err != nil { return nil, err } // Execute the template with the file content and write the output to the destination file ret := bytes.Buffer{} err = t.Execute(&ret, templateData) if err != nil { return nil, err } return ret.Bytes(), nil } // indent given string with given number of spaces whenever a newline symbol is found. func templateIndentNewlines(n int, val string) string { return strings.Replace(val, "\n", "\n"+strings.Repeat(" ", n), -1) } ================================================ FILE: pkg/util/fs/fs.go ================================================ package fs import ( "errors" "fmt" "github.com/cnoe-io/idpbuilder/pkg/util/files" "io" "io/fs" "os" "path" "path/filepath" ) type FS interface { ReadDir(name string) ([]fs.DirEntry, error) ReadFile(name string) ([]byte, error) } func ConvertFSToBytes(inFS FS, name string, templateData any) ([][]byte, error) { d, err := inFS.ReadDir(name) if err != nil { return nil, err } var rawResources [][]byte for _, f := range d { rawResource, err := inFS.ReadFile(path.Join(name, f.Name())) if err != nil { return nil, err } if returnedRawResource, err := files.ApplyTemplate(rawResource, templateData); err == nil { rawResources = append(rawResources, returnedRawResource) } else { return nil, err } } return rawResources, nil } func CopyFile(src fs.File, dest string) error { srcStat, srcStatErr := src.Stat() if srcStatErr != nil { return srcStatErr } destFn := filepath.Join(dest, srcStat.Name()) destf, destErr := os.OpenFile( destFn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, srcStat.Mode(), ) if destErr != nil { return fmt.Errorf("opening a file for writing: %w", destErr) } _, err := io.Copy(destf, src) if err != nil { return fmt.Errorf("copying %s to %s", srcStat.Name(), destFn) } return destf.Close() } func CopyDir(src fs.FS, dest string) error { ents, err := fs.ReadDir(src, ".") if err != nil { return fmt.Errorf("reading src: %w", err) } for _, sdent := range ents { info, err := sdent.Info() if err != nil { return fmt.Errorf("reading file info: %v", err) } switch { case info.IsDir(): subDest := filepath.Join(dest, sdent.Name()) if err := os.Mkdir(subDest, 0700); err != nil { return fmt.Errorf("mkdir on %s: %w", subDest, err) } subFS, err := fs.Sub(src, sdent.Name()) if err != nil { return fmt.Errorf("reading the sub directory: %w", err) } if err := CopyDir(subFS, subDest); err != nil { return err } case info.Mode().IsRegular(): srcf, err := src.Open(info.Name()) if err != nil { return err } if err := CopyFile(srcf, dest); err != nil { return err } } } return nil } func WriteFS(src fs.FS, dest string) error { destInfo, destErr := os.Lstat(dest) if destErr != nil { return destErr } if !destInfo.IsDir() { return errors.New("the destination must be a directory") } return CopyDir(src, dest) } ================================================ FILE: pkg/util/fs/fs_test.go ================================================ package fs import ( "fmt" "io/fs" "os" "path/filepath" "testing" "testing/fstest" "github.com/cnoe-io/idpbuilder/globals" "github.com/google/go-cmp/cmp" ) func TestWriteFS(t *testing.T) { cases := []struct { name string srcFS fs.FS expectErr error expectFiles map[string][]byte }{{ name: "single file", srcFS: fstest.MapFS{ "testfile": &fstest.MapFile{ Data: []byte("testdata"), Mode: 0666, }, }, expectFiles: map[string][]byte{ "testfile": []byte("testdata"), }, }, { name: "file in subdir", srcFS: fstest.MapFS{ "somedir": &fstest.MapFile{ Mode: fs.ModeDir, }, "somedir/testfile": &fstest.MapFile{ Data: []byte("testdata"), Mode: 0666, }, }, expectFiles: map[string][]byte{ "somedir/testfile": []byte("testdata"), }, }} for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { workDir, err := os.MkdirTemp("", fmt.Sprintf("%s-fs_test.go-%s", globals.ProjectName, tc.name)) if err != nil { t.Fatalf("creating tempdir: %v", err) } defer os.RemoveAll(workDir) err = WriteFS(tc.srcFS, workDir) if err != tc.expectErr { t.Errorf("unexpected error writing fs: %v", err) } for expectPath, expectData := range tc.expectFiles { fullExpectPath := filepath.Join(workDir, expectPath) gotData, err := os.ReadFile(fullExpectPath) if err != nil { t.Errorf("Opening expected file: %v", err) } if diff := cmp.Diff(string(expectData), string(gotData)); diff != "" { t.Errorf("Expected data in %q mismatch (-want +got):\n%s", expectPath, diff) } } }) } } ================================================ FILE: pkg/util/git_repository.go ================================================ package util import ( "bytes" "context" "crypto/sha256" "encoding/hex" "errors" "fmt" "io" "path/filepath" "strings" "sync" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/storage/memory" ) type RepoMap struct { repos sync.Map } func (r *RepoMap) LoadOrStore(repoName, dir string) *RepoState { v, _ := r.repos.LoadOrStore(repoName, &RepoState{Dir: dir}) return v.(*RepoState) } type RepoState struct { MU sync.Mutex Dir string } func NewRepoLock() *RepoMap { return &RepoMap{ repos: sync.Map{}, } } func RepoUrlHash(repoUrl string) string { sha := sha256.New() sha.Write([]byte(repoUrl)) return hex.EncodeToString(sha.Sum(nil)) } func RepoDir(repoUrl, parent string) string { return filepath.Join(parent, RepoUrlHash(repoUrl)) } func FirstRemoteURL(repo *git.Repository) (string, error) { remotes, err := repo.Remotes() if err != nil { return "", err } if len(remotes) <= 0 { return "", fmt.Errorf("no remotes found") } r := remotes[0].Config().URLs if len(r) <= 0 { return "", fmt.Errorf("no remote url found") } return r[0], nil } // returns all files with yaml or yml suffix from a worktree func GetWorktreeYamlFiles(parent string, wt billy.Filesystem, recurse bool) ([]string, error) { if strings.HasSuffix(parent, "/") { parent = strings.TrimSuffix(parent, "/") } paths := make([]string, 0, 10) ents, err := wt.ReadDir(parent) if err != nil { return nil, err } for i := range ents { ent := ents[i] if ent.IsDir() && recurse { dir := fmt.Sprintf("%s/%s", parent, ent.Name()) rPaths, dErr := GetWorktreeYamlFiles(dir, wt, recurse) if dErr != nil { return nil, fmt.Errorf("reading %s : %w", ent.Name(), dErr) } paths = append(paths, rPaths...) } if ent.Mode().IsRegular() && IsYamlFile(ent.Name()) { paths = append(paths, fmt.Sprintf("%s/%s", parent, ent.Name())) } } return paths, nil } func ReadWorktreeFile(wt billy.Filesystem, path string) ([]byte, error) { f, fErr := wt.Open(path) if fErr != nil { return nil, fmt.Errorf("opening %s", path) } defer f.Close() b := new(bytes.Buffer) _, fErr = b.ReadFrom(f) if fErr != nil { return nil, fmt.Errorf("reading %s", path) } return b.Bytes(), nil } func CloneRemoteRepoToMemory(ctx context.Context, remote v1alpha1.RemoteRepositorySpec, depth int, insecureSkipTLS bool) (billy.Filesystem, *git.Repository, error) { cloneOptions := &git.CloneOptions{ URL: remote.Url, Depth: depth, ShallowSubmodules: true, SingleBranch: true, Tags: git.AllTags, InsecureSkipTLS: insecureSkipTLS, } if remote.CloneSubmodules { cloneOptions.RecurseSubmodules = git.DefaultSubmoduleRecursionDepth } if remote.Ref != "" { cloneOptions.ReferenceName = plumbing.NewTagReferenceName(remote.Ref) } wt := memfs.New() var cloned *git.Repository cloned, err := git.CloneContext(ctx, memory.NewStorage(), wt, cloneOptions) if err != nil { cloneOptions.ReferenceName = plumbing.NewBranchReferenceName(remote.Ref) cloned, err = git.CloneContext(ctx, memory.NewStorage(), wt, cloneOptions) if err != nil { return nil, nil, err } } return wt, cloned, nil } func CloneRemoteRepoToDir(ctx context.Context, remote v1alpha1.RemoteRepositorySpec, depth int, insecureSkipTLS bool, dir, fallbackUrl string) (billy.Filesystem, *git.Repository, error) { repo, err := git.PlainOpen(dir) if err != nil { if errors.Is(err, git.ErrRepositoryNotExists) { cloneOptions := &git.CloneOptions{ URL: remote.Url, Depth: depth, ShallowSubmodules: true, Tags: git.AllTags, InsecureSkipTLS: insecureSkipTLS, } if remote.CloneSubmodules { cloneOptions.RecurseSubmodules = git.DefaultSubmoduleRecursionDepth } repo, err = git.PlainCloneContext(ctx, dir, false, cloneOptions) if err != nil { if fallbackUrl != "" { cloneOptions.URL = fallbackUrl repo, err = git.PlainCloneContext(ctx, dir, false, cloneOptions) if err != nil { return nil, nil, fmt.Errorf("cloning repo with fall back url: %w", err) } } else { return nil, nil, fmt.Errorf("cloning repo: %w", err) } } } else { return nil, nil, fmt.Errorf("opening repo at %s %w", dir, err) } } wt, err := repo.Worktree() if err != nil { return nil, nil, fmt.Errorf("getting repo worktree: %w", err) } if remote.Ref != "" { cErr := checkoutCommitOrRef(ctx, wt, remote.Ref) if cErr != nil { return nil, nil, fmt.Errorf("checkout %s: %w", remote.Ref, cErr) } } return wt.Filesystem, repo, nil } func CopyTreeToTree(srcWT, dstWT billy.Filesystem, srcPath, dstPath string) error { files, err := srcWT.ReadDir(srcPath) if err != nil { return err } for i := range files { srcFile := files[i] fullSrcPath := filepath.Join(srcPath, srcFile.Name()) fullDstPath := filepath.Join(dstPath, srcFile.Name()) if srcFile.Mode().IsRegular() { cErr := CopyWTFile(srcWT, dstWT, fullSrcPath, fullDstPath) if cErr != nil { return cErr } continue } if srcFile.IsDir() { dErr := CopyTreeToTree(srcWT, dstWT, fullSrcPath, fullDstPath) if dErr != nil { return dErr } } } return nil } func CopyWTFile(srcWT, dstWT billy.Filesystem, srcFile, dstFile string) error { newFile, err := dstWT.Create(dstFile) if err != nil { return fmt.Errorf("creating file %s: %w", dstFile, err) } defer newFile.Close() srcF, err := srcWT.Open(srcFile) if err != nil { return fmt.Errorf("reading file %s: %w", srcFile, err) } defer srcF.Close() _, err = io.Copy(newFile, srcF) if err != nil { return fmt.Errorf("copying file %s: %w", srcFile, err) } return nil } // ref could be anything. Check if hash, tag, or branch in that order func checkoutCommitOrRef(ctx context.Context, wt *git.Worktree, ref string) error { var refName plumbing.ReferenceName opts := &git.CheckoutOptions{ Hash: plumbing.NewHash(ref), } err := wt.Checkout(opts) if err != nil { refName = plumbing.NewTagReferenceName(ref) opts = &git.CheckoutOptions{ Branch: refName, } err := wt.Checkout(opts) if err != nil { refName = plumbing.NewBranchReferenceName(ref) opts = &git.CheckoutOptions{ Branch: refName, } err := wt.Checkout(opts) if err != nil { return err } } } pullOpts := &git.PullOptions{ RemoteName: "origin", } if opts.Hash.IsZero() { pullOpts.ReferenceName = refName err = wt.PullContext(ctx, pullOpts) if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) { return fmt.Errorf("pulling latest %s: %w", ref, err) } } return nil } ================================================ FILE: pkg/util/git_repository_test.go ================================================ package util import ( "context" "os" "path/filepath" "strings" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/storage/memory" "github.com/stretchr/testify/assert" ) func TestCloneRemoteRepoToDir(t *testing.T) { spec := v1alpha1.RemoteRepositorySpec{ CloneSubmodules: false, Path: "examples/basic", Url: "https://github.com/cnoe-io/idpbuilder", Ref: "v0.3.0", } dir, _ := os.MkdirTemp("", "TestCopyToDir") defer os.RemoveAll(dir) // new clone _, _, err := CloneRemoteRepoToDir(context.Background(), spec, 0, false, dir, "") assert.Nil(t, err) testDir, _ := os.MkdirTemp("", "TestCopyToDir") defer os.RemoveAll(testDir) repo, err := git.PlainClone(testDir, false, &git.CloneOptions{URL: dir}) assert.Nil(t, err) ref, err := repo.Head() assert.Nil(t, err) assert.Equal(t, "52783df3a8942cc882ebeb6168f80e1876a2f129", ref.Hash().String()) // existing spec.Ref = "v0.4.0" testDir2, _ := os.MkdirTemp("", "TestCopyToDir") defer os.RemoveAll(testDir2) _, _, err = CloneRemoteRepoToDir(context.Background(), spec, 0, false, dir, "") repo, err = git.PlainClone(testDir2, false, &git.CloneOptions{URL: dir}) assert.Nil(t, err) ref, err = repo.Head() assert.Nil(t, err) assert.Equal(t, "11eccd57fde9f4ef6de8bfa1fc11d168a4d30fe1", ref.Hash().String()) assert.Nil(t, err) } func TestCopyTreeToTree(t *testing.T) { spec := v1alpha1.RemoteRepositorySpec{ CloneSubmodules: false, Path: "examples/basic", Url: "https://github.com/cnoe-io/idpbuilder", Ref: "", } dst := memfs.New() src, _, err := CloneRemoteRepoToMemory(context.Background(), spec, 1, false) assert.Nil(t, err) err = CopyTreeToTree(src, dst, spec.Path, ".") assert.Nil(t, err) testCopiedFiles(t, src, dst, spec.Path, ".") } func testCopiedFiles(t *testing.T, src, dst billy.Filesystem, srcStartPath, dstStartPath string) { files, err := src.ReadDir(srcStartPath) assert.Nil(t, err) for i := range files { file := files[i] if file.Mode().IsRegular() { srcB, err := ReadWorktreeFile(src, filepath.Join(srcStartPath, file.Name())) assert.Nil(t, err) dstB, err := ReadWorktreeFile(dst, filepath.Join(dstStartPath, file.Name())) assert.Nil(t, err) assert.Equal(t, srcB, dstB) } if file.IsDir() { testCopiedFiles(t, src, dst, filepath.Join(srcStartPath, file.Name()), filepath.Join(dstStartPath, file.Name())) } } } func TestGetWorktreeYamlFiles(t *testing.T) { filepath.Join() cloneOptions := &git.CloneOptions{ URL: "https://github.com/cnoe-io/idpbuilder", Depth: 1, ShallowSubmodules: true, } wt := memfs.New() _, err := git.CloneContext(context.Background(), memory.NewStorage(), wt, cloneOptions) if err != nil { t.Fatalf(err.Error()) } paths, err := GetWorktreeYamlFiles("./pkg", wt, true) assert.Equal(t, nil, err) assert.NotEqual(t, 0, len(paths)) for _, s := range paths { assert.Equal(t, true, strings.HasSuffix(s, "yaml") || strings.HasSuffix(s, "yml")) } paths, err = GetWorktreeYamlFiles("./pkg", wt, false) assert.Equal(t, nil, err) assert.Equal(t, 0, len(paths)) } ================================================ FILE: pkg/util/gitea.go ================================================ package util import ( "code.gitea.io/sdk/gitea" "context" "encoding/base64" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "strings" ) const ( // hardcoded values from what we have in the yaml installation file. GiteaNamespace = "gitea" GiteaAdminSecret = "gitea-credential" GiteaAdminName = "giteaAdmin" GiteaAdminTokenName = "admin" GiteaAdminTokenFieldName = "token" GiteaURLTempl = "%s://%s%s:%s%s" ) func GiteaAdminSecretObject() corev1.Secret { return corev1.Secret{ TypeMeta: metav1.TypeMeta{ Kind: "Secret", APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: GiteaAdminSecret, Namespace: GiteaNamespace, }, } } func PatchPasswordSecret(ctx context.Context, kubeClient client.Client, config v1alpha1.BuildCustomizationSpec, ns string, secretName string, username string, pass string) error { sec, err := GetSecretByName(ctx, kubeClient, ns, secretName) if err != nil { return fmt.Errorf("getting secret to patch fails: %w", err) } u := unstructured.Unstructured{} u.SetName(sec.GetName()) u.SetNamespace(sec.GetNamespace()) u.SetGroupVersionKind(sec.GetObjectKind().GroupVersionKind()) err = unstructured.SetNestedField(u.Object, base64.StdEncoding.EncodeToString([]byte(pass)), "data", "password") if err != nil { return fmt.Errorf("setting password field: %w", err) } if strings.Contains(secretName, "gitea") { // We should recreate a token as user/password changed giteaUrl := GiteaBaseUrl(config) t, err := GetGiteaToken(ctx, giteaUrl, string(username), string(pass)) if err != nil { return fmt.Errorf("getting gitea token: %w", err) } token := base64.StdEncoding.EncodeToString([]byte(t)) err = unstructured.SetNestedField(u.Object, token, "data", GiteaAdminTokenFieldName) if err != nil { return fmt.Errorf("setting gitea token field: %w", err) } } return kubeClient.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) } func GetGiteaToken(ctx context.Context, baseUrl, username, password string) (string, error) { giteaClient, err := gitea.NewClient(baseUrl, gitea.SetHTTPClient(GetHttpClient()), gitea.SetBasicAuth(username, password), gitea.SetContext(ctx), ) if err != nil { return "", fmt.Errorf("creating gitea client: %w", err) } tokens, resp, err := giteaClient.ListAccessTokens(gitea.ListAccessTokensOptions{}) if err != nil { return "", fmt.Errorf("listing gitea access tokens. status: %s error : %w", resp.Status, err) } for i := range tokens { if tokens[i].Name == GiteaAdminTokenName { resp, err := giteaClient.DeleteAccessToken(tokens[i].ID) if err != nil { return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) } break } } token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{ Name: GiteaAdminTokenName, Scopes: []gitea.AccessTokenScope{ gitea.AccessTokenScopeAll, }, }) if err != nil { return "", fmt.Errorf("deleting gitea access tokens. status: %s error : %w", resp.Status, err) } return token.Token, nil } func GiteaBaseUrl(config v1alpha1.BuildCustomizationSpec) string { if config.UsePathRouting { return fmt.Sprintf(GiteaURLTempl, config.Protocol, "", config.Host, config.Port, "/gitea") } return fmt.Sprintf(GiteaURLTempl, config.Protocol, "gitea.", config.Host, config.Port, "") } ================================================ FILE: pkg/util/gitea_test.go ================================================ package util import ( "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/stretchr/testify/assert" ) func TestGiteaBaseUrl(t *testing.T) { c := v1alpha1.BuildCustomizationSpec{ Protocol: "http", Port: "8080", Host: "cnoe.localtest.me", UsePathRouting: false, } s := GiteaBaseUrl(c) assert.Equal(t, "http://gitea.cnoe.localtest.me:8080", s) c.UsePathRouting = true s = GiteaBaseUrl(c) assert.Equal(t, "http://cnoe.localtest.me:8080/gitea", s) } ================================================ FILE: pkg/util/idp.go ================================================ package util import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/client" ) func GetConfig(ctx context.Context) (v1alpha1.BuildCustomizationSpec, error) { b := v1alpha1.BuildCustomizationSpec{} kubeConfig, err := GetKubeConfig() if err != nil { return b, fmt.Errorf("getting kube config: %w", err) } kubeClient, err := GetKubeClient(kubeConfig) if err != nil { return b, fmt.Errorf("getting kube client: %w", err) } list, err := getLocalBuild(ctx, kubeClient) if err != nil { return b, err } // TODO: We assume that only one LocalBuild exists ! return list.Items[0].Spec.BuildCustomization, nil } func getLocalBuild(ctx context.Context, kubeClient client.Client) (v1alpha1.LocalbuildList, error) { localBuildList := v1alpha1.LocalbuildList{} return localBuildList, kubeClient.List(ctx, &localBuildList) } ================================================ FILE: pkg/util/k8s.go ================================================ package util import ( "fmt" "github.com/cnoe-io/idpbuilder/pkg/k8s" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/homedir" "path/filepath" "sigs.k8s.io/controller-runtime/pkg/client" ) var ( KubeConfigPath string ) func GetKubeConfigPath() string { if KubeConfigPath == "" { return filepath.Join(homedir.HomeDir(), ".kube", "config") } else { return KubeConfigPath } } func LoadKubeConfig() (*api.Config, error) { config, err := clientcmd.LoadFromFile(GetKubeConfigPath()) if err != nil { return nil, fmt.Errorf("Failed to load kubeconfig file: %w", err) } else { return config, nil } } func GetKubeConfig() (*rest.Config, error) { kubeConfig, err := clientcmd.BuildConfigFromFlags("", GetKubeConfigPath()) if err != nil { return nil, fmt.Errorf("Error building kubeconfig: %w", err) } return kubeConfig, nil } func GetKubeClient(kubeConfig *rest.Config) (client.Client, error) { kubeClient, err := client.New(kubeConfig, client.Options{Scheme: k8s.GetScheme()}) if err != nil { return nil, fmt.Errorf("Error creating kubernetes client: %w", err) } return kubeClient, nil } ================================================ FILE: pkg/util/secret.go ================================================ package util import ( "context" v1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) func GetSecretByName(ctx context.Context, kubeClient client.Client, ns, name string) (v1.Secret, error) { s := v1.Secret{} return s, kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: ns}, &s) } ================================================ FILE: pkg/util/url.go ================================================ package util import ( "fmt" "net/url" "strconv" "strings" "time" ) // constants from remote target parameters supported by Kustomize // https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md const ( QueryStringRef = "ref" QueryStringVersion = "version" QueryStringTimeout = "timeout" QueryStringSubmodules = "submodules" RepoUrlDelimiter = "//" SCPDelimiter = ":" UserDelimiter = "@" defaultTimeout = time.Second * 27 defaultCloneSubmodule = true errMsgUrlUnsupported = "url must have // after the repository url. example: https://github.com/kubernetes-sigs/kustomize//examples" errMsgUrlColon = "first path segment in URL cannot contain colon" ) type KustomizeRemote struct { raw string Scheme string User string Password string Host string Port string RepoPath string FilePath string Ref string Submodules bool Timeout time.Duration } func (g *KustomizeRemote) CloneUrl() string { sb := strings.Builder{} if g.Scheme != "" { sb.WriteString(fmt.Sprintf("%s://", g.Scheme)) } if g.User != "" { sb.WriteString(g.User) if g.Password != "" { sb.WriteString(fmt.Sprintf(":%s", g.Password)) } sb.Write([]byte(UserDelimiter)) } sb.WriteString(g.Host) if g.Port != "" { sb.WriteString(fmt.Sprintf(":%s", g.Port)) } if g.Scheme == "" { sb.WriteString(":") } else { sb.WriteString("/") } sb.WriteString(g.RepoPath) return sb.String() } func (g *KustomizeRemote) Path() string { return g.FilePath } func (g *KustomizeRemote) parseQuery() error { _, query, _ := strings.Cut(g.raw, "?") values, err := url.ParseQuery(query) if err != nil { return err } // if empty, it means we checkout the default branch version := values.Get(QueryStringVersion) ref := values.Get(QueryStringRef) // ref has higher priority per kustomize doc if ref != "" { version = ref } duration := defaultTimeout timeoutString := values.Get(QueryStringTimeout) if timeoutString != "" { timeoutInt, sErr := strconv.Atoi(timeoutString) if sErr == nil { duration = time.Duration(timeoutInt) * time.Second } else { t, sErr := time.ParseDuration(timeoutString) if sErr == nil { duration = t } } } cloneSubmodules := defaultCloneSubmodule submodule := values.Get(QueryStringSubmodules) if submodule != "" { v, pErr := strconv.ParseBool(submodule) if pErr == nil { cloneSubmodules = v } } g.Ref = version g.Submodules = cloneSubmodules g.Timeout = duration return nil } func (g *KustomizeRemote) parse() error { parsed, err := url.Parse(g.raw) if err != nil { if strings.Contains(err.Error(), errMsgUrlColon) { return g.parseSCPStyle() } return err } g.Scheme, g.User, g.Host = parsed.Scheme, parsed.User.Username(), parsed.Host p, ok := parsed.User.Password() if ok { g.Password = p } err = g.parseQuery() if err != nil { return fmt.Errorf("parsing query parameters in package url: %s: %w", g.raw, err) } return g.parsePath(parsed.Path) } func (g *KustomizeRemote) parseSCPStyle() error { // example git@github.com:owner/repo cIndex := strings.Index(g.raw, SCPDelimiter) if cIndex == -1 { return fmt.Errorf("not a valid SCP style URL") } uIndex := strings.Index(g.raw[:cIndex], UserDelimiter) if uIndex != -1 { g.User = g.raw[:uIndex] } g.Host = g.raw[uIndex+1 : cIndex] err := g.parseQuery() if err != nil { return fmt.Errorf("parsing query parameters in package url: %s: %w", g.raw, err) } pathEnd := len(g.raw) qIndex := strings.Index(g.raw, "?") if qIndex != -1 { pathEnd = qIndex } return g.parsePath(g.raw[cIndex+1 : pathEnd]) } func (g *KustomizeRemote) parsePath(path string) error { // example kubernetes-sigs/kustomize//examples/multibases/dev/ index := strings.Index(path, RepoUrlDelimiter) if index == -1 { return fmt.Errorf(errMsgUrlUnsupported) } g.RepoPath = strings.TrimPrefix(path[:index], "/") g.FilePath = strings.TrimSuffix(path[index+2:], "/") return nil } func NewKustomizeRemote(uri string) (*KustomizeRemote, error) { r := &KustomizeRemote{raw: uri} return r, r.parse() } ================================================ FILE: pkg/util/url_test.go ================================================ package util import ( "testing" "time" "github.com/stretchr/testify/assert" ) func TestURLParse(t *testing.T) { type expect struct { cloneUrl string path string ref string submodule bool timeout time.Duration err bool } type testCase struct { expect expect input string } cases := []testCase{ { input: "https://github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?timeout=120&ref=v3.3.1", expect: expect{ cloneUrl: "https://github.com/kubernetes-sigs/kustomize", path: "examples/multibases/dev", ref: "v3.3.1", submodule: true, timeout: 120 * time.Second, }, }, { input: "git@github.com:owner/repo//examples?timeout=120&version=v3.3.1", expect: expect{ cloneUrl: "git@github.com:owner/repo", path: "examples", ref: "v3.3.1", submodule: true, timeout: 120 * time.Second, }, }, { input: "https:// /(@kubernetes-sigs/kustomize//examples/multibases/dev/?timeout=120&ref=v3.3.1", expect: expect{ err: true, }, }, { input: "https://my.github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?version=v3.3.1&submodules=false&timeout=1s", expect: expect{ cloneUrl: "https://my.github.com/kubernetes-sigs/kustomize", path: "examples/multibases/dev", ref: "v3.3.1", submodule: false, timeout: 1 * time.Second, }, }, } for i := range cases { c := cases[i] r, err := NewKustomizeRemote(c.input) if err != nil { if !c.expect.err { assert.Fail(t, err.Error()) } else { continue } } assert.Equal(t, c.expect.path, r.Path()) assert.Equal(t, c.expect.cloneUrl, r.CloneUrl()) assert.Equal(t, c.expect.timeout, r.Timeout) assert.Equal(t, c.expect.ref, r.Ref) assert.Equal(t, c.expect.submodule, r.Submodules) } } ================================================ FILE: pkg/util/util.go ================================================ package util import ( "context" "crypto/rand" "crypto/tls" "fmt" "math" "math/big" mathrand "math/rand" "net" "net/http" "os" "path/filepath" "strings" "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" ) const ( chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" digits = "0123456789" specialChars = `!#$%&'()*+,-./:;<=>?@[]^_{|}~` passwordLength = 40 numSpecialChars = 3 numDigits = 3 StaticPassword = "developer" ) func GetCLIStartTimeAnnotationValue(annotations map[string]string) (string, error) { if annotations == nil { return "", fmt.Errorf("this object's annotation is nil") } timeStamp, ok := annotations[v1alpha1.CliStartTimeAnnotation] if ok { return timeStamp, nil } return "", fmt.Errorf("expected annotation, %s, not found", v1alpha1.CliStartTimeAnnotation) } func SetCLIStartTimeAnnotationValue(annotations map[string]string, timeStamp string) { if timeStamp != "" && annotations != nil { annotations[v1alpha1.CliStartTimeAnnotation] = timeStamp } } func SetLastObservedSyncTimeAnnotationValue(annotations map[string]string, timeStamp string) { if timeStamp != "" && annotations != nil { annotations[v1alpha1.LastObservedCLIStartTimeAnnotation] = timeStamp } } func GetLastObservedSyncTimeAnnotationValue(annotations map[string]string) (string, error) { if annotations == nil { return "", fmt.Errorf("this object's annotation is nil") } timeStamp, ok := annotations[v1alpha1.LastObservedCLIStartTimeAnnotation] if ok { return timeStamp, nil } return "", fmt.Errorf("expected annotation, %s, not found", v1alpha1.LastObservedCLIStartTimeAnnotation) } func UpdateSyncAnnotation(ctx context.Context, kubeClient client.Client, obj client.Object) error { timeStamp, err := GetCLIStartTimeAnnotationValue(obj.GetAnnotations()) if err != nil { return err } annotations := make(map[string]string, 1) SetLastObservedSyncTimeAnnotationValue(annotations, timeStamp) return ApplyAnnotation(ctx, kubeClient, obj, annotations, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager)) } func ApplyAnnotation(ctx context.Context, kubeClient client.Client, obj client.Object, annotations map[string]string, opts ...client.PatchOption) error { // MUST be unstructured to avoid managing fields we do not care about. u := unstructured.Unstructured{} u.SetAnnotations(annotations) u.SetName(obj.GetName()) u.SetNamespace(obj.GetNamespace()) u.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind()) return kubeClient.Patch(ctx, &u, client.Apply, opts...) } func GeneratePassword() (string, error) { passChars := make([]string, passwordLength) validChars := fmt.Sprintf("%s%s%s", chars, digits, specialChars) for i := 0; i < numSpecialChars; i++ { c, err := getRandElement(specialChars) if err != nil { return "", err } passChars = append(passChars, c) } for i := 0; i < numDigits; i++ { c, err := getRandElement(digits) if err != nil { return "", err } passChars = append(passChars, c) } for i := 0; i < passwordLength-numDigits-numSpecialChars; i++ { c, err := getRandElement(validChars) if err != nil { return "", err } passChars = append(passChars, c) } seed, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) if err != nil { return "", err } r := mathrand.New(mathrand.NewSource(seed.Int64())) r.Shuffle(len(passChars), func(i, j int) { passChars[i], passChars[j] = passChars[j], passChars[i] }) return strings.Join(passChars, ""), nil } func getRandElement(input string) (string, error) { position, err := rand.Int(rand.Reader, big.NewInt(int64(len(input)))) if err != nil { return "", err } return string(input[position.Int64()]), nil } func IsYamlFile(input string) bool { extension := filepath.Ext(input) return extension == ".yaml" || extension == ".yml" } func GetHttpClient() *http.Client { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, DialContext: (&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 30 * time.Second, // from http.DefaultTransport }).DialContext, } return &http.Client{Transport: tr, Timeout: 30 * time.Second} } // DetectKindNodeProvider follows the kind CLI convention where: // 1. if KIND_EXPERIMENTAL_PROVIDER env var is specified, it uses the value: // 2. if env var is not specified, use the first available supported engine. // https://github.com/kubernetes-sigs/kind/blob/ac81e7b64e06670132dae3486e64e531953ad58c/pkg/cluster/provider.go#L100-L114 func DetectKindNodeProvider() (cluster.ProviderOption, error) { switch p := os.Getenv("KIND_EXPERIMENTAL_PROVIDER"); p { case "podman": return cluster.ProviderWithPodman(), nil case "docker": return cluster.ProviderWithDocker(), nil case "nerdctl", "finch", "nerdctl.lima": return cluster.ProviderWithNerdctl(p), nil default: return cluster.DetectNodeProvider() } } func SetPackageLabels(obj client.Object) { labels := obj.GetLabels() if labels == nil { labels = map[string]string{} obj.SetLabels(labels) } labels[v1alpha1.PackageNameLabelKey] = obj.GetName() switch n := obj.GetName(); n { case v1alpha1.ArgoCDPackageName, v1alpha1.GiteaPackageName, v1alpha1.IngressNginxPackageName: labels[v1alpha1.PackageTypeLabelKey] = v1alpha1.PackageTypeLabelCore default: labels[v1alpha1.PackageTypeLabelKey] = v1alpha1.PackageTypeLabelCustom } } ================================================ FILE: pkg/util/util_test.go ================================================ package util import ( "strconv" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) var specialCharMap = make(map[string]struct{}) func TestGeneratePassword(t *testing.T) { for i := range specialChars { specialCharMap[string(specialChars[i])] = struct{}{} } for i := 0; i < 1000; i++ { p, err := GeneratePassword() if err != nil { t.Fatalf("error generating password: %v", err) } counts := make([]int, 3) for j := range p { counts[0] += 1 c := string(p[j]) _, ok := specialCharMap[c] if ok { counts[1] += 1 continue } _, err := strconv.Atoi(c) if err == nil { counts[2] += 1 } } if counts[0] != passwordLength { t.Fatalf("password length incorrect") } if counts[1] < numSpecialChars { t.Fatalf("min number of special chars not generated") } if counts[2] < numDigits { t.Fatalf("min number of digits not generated") } } } type MockObject struct { v1.ObjectMeta } func (m *MockObject) GetObjectKind() schema.ObjectKind { return nil } func (m *MockObject) DeepCopyObject() runtime.Object { return nil } func TestSetPackageLabels(t *testing.T) { testCases := []struct { name string objectName string initialLabels map[string]string expectedLabels map[string]string }{ { name: "No initial labels", objectName: "test-package", initialLabels: nil, expectedLabels: map[string]string{ v1alpha1.PackageNameLabelKey: "test-package", v1alpha1.PackageTypeLabelKey: v1alpha1.PackageTypeLabelCustom, }, }, { name: "With initial labels", objectName: "test-package-one", initialLabels: map[string]string{ "existing": "label", v1alpha1.PackageNameLabelKey: "incorrect", }, expectedLabels: map[string]string{ "existing": "label", v1alpha1.PackageNameLabelKey: "test-package-one", v1alpha1.PackageTypeLabelKey: v1alpha1.PackageTypeLabelCustom, }, }, { name: "ArgoCD package", objectName: v1alpha1.ArgoCDPackageName, initialLabels: nil, expectedLabels: map[string]string{ v1alpha1.PackageNameLabelKey: v1alpha1.ArgoCDPackageName, v1alpha1.PackageTypeLabelKey: v1alpha1.PackageTypeLabelCore, }, }, { name: "Gitea package", objectName: v1alpha1.GiteaPackageName, initialLabels: nil, expectedLabels: map[string]string{ v1alpha1.PackageNameLabelKey: v1alpha1.GiteaPackageName, v1alpha1.PackageTypeLabelKey: v1alpha1.PackageTypeLabelCore, }, }, { name: "IngressNginx package", objectName: v1alpha1.IngressNginxPackageName, initialLabels: nil, expectedLabels: map[string]string{ v1alpha1.PackageNameLabelKey: v1alpha1.IngressNginxPackageName, v1alpha1.PackageTypeLabelKey: v1alpha1.PackageTypeLabelCore, }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { obj := &MockObject{ ObjectMeta: v1.ObjectMeta{ Name: tc.objectName, Labels: tc.initialLabels, }, } SetPackageLabels(obj) assert.Equal(t, tc.expectedLabels, obj.GetLabels()) }) } } ================================================ FILE: tests/e2e/docker/docker_test.go ================================================ //go:build e2e package docker import ( "context" "fmt" "log/slog" "os" "os/exec" "strings" "testing" "time" "github.com/cnoe-io/idpbuilder/tests/e2e" "github.com/go-logr/logr" "github.com/stretchr/testify/assert" ctrl "sigs.k8s.io/controller-runtime" ) func CleanUpDocker(t *testing.T) { t.Log("cleaning up docker env") ctx, cancel := context.WithCancel(context.Background()) defer cancel() b, err := e2e.RunCommand(ctx, `docker ps -aqf name=localdev-control-plane`, 10*time.Second) assert.NoError(t, err, fmt.Sprintf("error while listing docker containers: %s, %s", err, b)) conts := strings.TrimSpace(string(b)) if len(conts) == 0 { return } b, err = e2e.RunCommand(ctx, fmt.Sprintf("docker container rm -f %s", conts), 60*time.Second) assert.NoError(t, err, fmt.Sprintf("error while removing docker containers: %s, %s", err, b)) b, err = e2e.RunCommand(ctx, "docker system prune -f", 60*time.Second) assert.NoError(t, err, fmt.Sprintf("error while pruning system: %s, %s", err, b)) b, err = e2e.RunCommand(ctx, "docker volume prune -f", 60*time.Second) assert.NoError(t, err, fmt.Sprintf("error while pruning volumes: %s, %s", err, b)) t.Log("finished cleaning up docker env") } func Test_CreateDocker(t *testing.T) { slogger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug})) ctrl.SetLogger(logr.FromSlogHandler(slogger.Handler())) testCreate(t) testCreatePath(t) testCreatePort(t) testCustomPkg(t) testPackagePriority(t) } // test idpbuilder create func testCreate(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute) defer cancel() defer CleanUpDocker(t) t.Log("running idpbuilder create") cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create") b, err := cmd.CombinedOutput() assert.NoError(t, err, b) kubeClient, err := e2e.GetKubeClient() assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err)) e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages) argoBaseUrl := fmt.Sprintf("https://argocd.%s:%s", e2e.DefaultBaseDomain, e2e.DefaultPort) giteaBaseUrl := fmt.Sprintf("https://gitea.%s:%s", e2e.DefaultBaseDomain, e2e.DefaultPort) e2e.TestCoreEndpoints(ctx, t, argoBaseUrl, giteaBaseUrl) e2e.TestGiteaRegistry(ctx, t, "docker", fmt.Sprintf("gitea.%s", e2e.DefaultBaseDomain), e2e.DefaultPort) } // test idpbuilder create --use-path-routing func testCreatePath(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute) defer cancel() defer CleanUpDocker(t) t.Log("running idpbuilder create --use-path-routing") cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create", "--use-path-routing") b, err := cmd.CombinedOutput() assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b)) kubeClient, err := e2e.GetKubeClient() assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err)) e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages) argoBaseUrl := fmt.Sprintf("https://%s:%s/argocd", e2e.DefaultBaseDomain, e2e.DefaultPort) giteaBaseUrl := fmt.Sprintf("https://%s:%s/gitea", e2e.DefaultBaseDomain, e2e.DefaultPort) e2e.TestCoreEndpoints(ctx, t, argoBaseUrl, giteaBaseUrl) e2e.TestGiteaRegistry(ctx, t, "docker", e2e.DefaultBaseDomain, e2e.DefaultPort) e2e.TestGiteaRegistryInCluster(ctx, t, "docker", e2e.DefaultBaseDomain, e2e.DefaultPort, kubeClient) } func testCreatePort(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute) defer cancel() defer CleanUpDocker(t) port := "2443" t.Logf("running idpbuilder create --port %s", port) cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create", "--port", port) b, err := cmd.CombinedOutput() assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b)) kubeClient, err := e2e.GetKubeClient() assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err)) e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages) argoBaseUrl := fmt.Sprintf("https://argocd.%s:%s", e2e.DefaultBaseDomain, port) giteaBaseUrl := fmt.Sprintf("https://gitea.%s:%s", e2e.DefaultBaseDomain, port) e2e.TestCoreEndpoints(ctx, t, argoBaseUrl, giteaBaseUrl) } func testCustomPkg(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute) defer cancel() defer CleanUpDocker(t) cmdString := "create --package ../../../pkg/controllers/custompackage/test/resources/customPackages/testDir" t.Log(fmt.Sprintf("running %s", cmdString)) cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, strings.Split(cmdString, " ")...) b, err := cmd.CombinedOutput() assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b)) kubeClient, err := e2e.GetKubeClient() assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err)) if err != nil { assert.FailNow(t, "failed creating cluster") } e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages) giteaBaseUrl := fmt.Sprintf("https://gitea.%s:%s", e2e.DefaultBaseDomain, e2e.DefaultPort) expectedApps := map[string]string{ "my-app": "argocd", "my-app2": "argocd", } e2e.TestArgoCDApps(ctx, t, kubeClient, expectedApps) repos, err := e2e.GetGiteaRepos(ctx, giteaBaseUrl) assert.NoError(t, err) expectedRepoNames := map[string]struct{}{ "idpbuilder-localdev-my-app-app1": {}, "idpbuilder-localdev-my-app2-app2": {}, } for i := range repos { repo := repos[i] _, ok := expectedRepoNames[repo.Name] if ok { delete(expectedRepoNames, repo.Name) } } assert.Empty(t, expectedRepoNames) } // testPackagePriority tests the priority-based package reconciliation feature // where multiple packages for the same app can be specified, and only the highest priority wins func testPackagePriority(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 8*time.Minute) defer cancel() defer CleanUpDocker(t) // Create with multiple package directories // The packages will be assigned priorities based on their order (0, 1, 2, ...) cmdString := "create --package ../../../pkg/controllers/custompackage/test/resources/customPackages/testDir --package ../../../pkg/controllers/custompackage/test/resources/customPackages/testDir2" t.Log(fmt.Sprintf("running %s to test package priority", cmdString)) cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, strings.Split(cmdString, " ")...) b, err := cmd.CombinedOutput() assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b)) kubeClient, err := e2e.GetKubeClient() assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err)) if err != nil { assert.FailNow(t, "failed creating cluster") } // Wait for core packages to be ready e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages) // Verify CustomPackages have priority annotations t.Log("Verifying CustomPackages have correct priority annotations") customPkgList := &e2e.CustomPackageList{} err = kubeClient.List(ctx, customPkgList, &e2e.ListOptions{Namespace: "idpbuilder-localdev"}) assert.NoError(t, err, "failed to list custom packages") // Verify that packages have priority annotations foundPriorities := make(map[string]string) for _, pkg := range customPkgList.Items { if pkg.ObjectMeta.Annotations != nil { if priority, exists := pkg.ObjectMeta.Annotations["cnoe.io/package-priority"]; exists { t.Logf("Package %s has priority: %s", pkg.Name, priority) foundPriorities[pkg.Name] = priority } if sourcePath, exists := pkg.ObjectMeta.Annotations["cnoe.io/package-source-path"]; exists { t.Logf("Package %s has source path: %s", pkg.Name, sourcePath) } } } // At least some packages should have priority annotations assert.NotEmpty(t, foundPriorities, "expected custom packages to have priority annotations") // Wait for custom packages to reconcile time.Sleep(10 * time.Second) // Verify apps are deployed expectedApps := map[string]string{ "my-app": "argocd", "guestbook": "argocd", } e2e.TestArgoCDApps(ctx, t, kubeClient, expectedApps) t.Log("Package priority test completed successfully") } ================================================ FILE: tests/e2e/docker/test-dockerfile ================================================ FROM scratch COPY test-dockerfile . ================================================ FILE: tests/e2e/e2e.go ================================================ //go:build e2e package e2e import ( "bytes" "context" "crypto/tls" "encoding/json" "fmt" "io" "net/http" "os/exec" "path/filepath" "strings" "testing" "time" "code.gitea.io/sdk/gitea" argov1alpha1 "github.com/cnoe-io/argocd-api/api/argo/application/v1alpha1" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/printer/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "k8s.io/client-go/util/retry" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" ) // Type aliases for convenience type CustomPackageList = v1alpha1.CustomPackageList type ListOptions = client.ListOptions const ( IdpbuilderBinaryLocation = "../../../idpbuilder" DefaultPort = "8443" DefaultBaseDomain = "cnoe.localtest.me" ArgoCDSessionEndpoint = "/api/v1/session" ArgoCDAppsEndpoint = "/api/v1/applications" GiteaSessionEndpoint = "/api/v1/users/%s/tokens" GiteaUserEndpoint = "/api/v1/users/%s" GiteaRepoEndpoint = "/api/v1/repos/search" httpRetryDelay = 5 * time.Second httpRetryTimeout = 300 * time.Second ) var ( // CorePackages is a map of argocd app name to its namespace. CorePackages = map[string]string{ "argocd": "argocd", "nginx": "argocd", "gitea": "argocd", } ) type BasicAuth struct { Username string `json:"username"` Password string `json:"password"` } type ArgoCDAuthResponse struct { Token string `json:"token"` } type ArgoCDAppResp struct { Items []argov1alpha1.Application } type GiteaSearchRepoResponse struct { Ok bool Data []gitea.Repository } func GetHttpClient() *http.Client { tr := http.DefaultTransport.(*http.Transport).Clone() tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} return &http.Client{Transport: tr} } func TestCoreEndpoints(ctx context.Context, t *testing.T, argoBaseUrl, giteaBaseUrl string) { TestArgoCDEndpoints(ctx, t, argoBaseUrl) TestGiteaEndpoints(ctx, t, giteaBaseUrl) } func RunCommand(ctx context.Context, command string, timeout time.Duration) ([]byte, error) { cmdCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() cmds := strings.Split(command, " ") if len(cmds) == 0 { return nil, fmt.Errorf("supply at least one command") } binary := cmds[0] args := make([]string, 0, len(cmds)-1) if len(cmds) > 1 { args = append(args, cmds[1:]...) } c := exec.CommandContext(cmdCtx, binary, args...) b, err := c.CombinedOutput() if err != nil { return nil, fmt.Errorf("error while running %s: %s, %s", command, err, b) } return b, nil } func SendAndParse(ctx context.Context, target any, httpClient *http.Client, req *http.Request) error { sendCtx, cancel := context.WithTimeout(ctx, httpRetryTimeout) defer cancel() var bodyBytes []byte if req.Body != nil { b, bErr := io.ReadAll(req.Body) if bErr != nil { return fmt.Errorf("failed copying http request body: %w", bErr) } bodyBytes = b } for { select { case <-sendCtx.Done(): return fmt.Errorf("timedout") default: if req.Body != nil { b := append(make([]byte, 0, len(bodyBytes)), bodyBytes...) req.Body = io.NopCloser(bytes.NewBuffer(b)) } resp, err := httpClient.Do(req) if err != nil { fmt.Println("failed running http request: ", err) time.Sleep(httpRetryDelay) continue } defer resp.Body.Close() respB, err := io.ReadAll(resp.Body) if err != nil { fmt.Println("failed reading http response body: ", err) time.Sleep(httpRetryDelay) continue } err = json.Unmarshal(respB, target) if err != nil { fmt.Println("failed parsing response body: ", err, "\n", string(respB)) time.Sleep(httpRetryDelay) continue } return nil } } } func TestGiteaEndpoints(ctx context.Context, t *testing.T, baseUrl string) { t.Log("testing gitea endpoints") repos, err := GetGiteaRepos(ctx, baseUrl) assert.Nil(t, err) assert.Equal(t, 3, len(repos)) expectedRepoNames := map[string]struct{}{ "idpbuilder-localdev-gitea": {}, "idpbuilder-localdev-nginx": {}, "idpbuilder-localdev-argocd": {}, } for i := range repos { _, ok := expectedRepoNames[repos[i].Name] if ok { delete(expectedRepoNames, repos[i].Name) } } assert.Equal(t, 0, len(expectedRepoNames)) } func GetGiteaRepos(ctx context.Context, baseUrl string) ([]gitea.Repository, error) { auth, err := GetBasicAuth(ctx, "gitea-credential") if err != nil { return nil, fmt.Errorf("getting gitea credentials %w", err) } token, err := GetGiteaSessionToken(ctx, auth, baseUrl) if err != nil { return nil, fmt.Errorf("getting gitea token %w", err) } userEP := fmt.Sprintf("%s%s", baseUrl, fmt.Sprintf(GiteaUserEndpoint, auth.Username)) req, err := http.NewRequestWithContext(ctx, http.MethodGet, userEP, nil) if err != nil { return nil, fmt.Errorf("creating new request %w", err) } httpClient := GetHttpClient() req.Header.Set("Authorization", fmt.Sprintf("token %s", token)) user := gitea.User{} err = SendAndParse(ctx, &user, httpClient, req) if err != nil { return nil, fmt.Errorf("getting user info %w", err) } repos := GiteaSearchRepoResponse{} repoEp := fmt.Sprintf("%s%s", baseUrl, GiteaRepoEndpoint) repoReq, _ := http.NewRequestWithContext(ctx, http.MethodGet, repoEp, nil) err = SendAndParse(ctx, &repos, httpClient, repoReq) if err != nil { return nil, fmt.Errorf("getting gitea repositories %w", err) } return repos.Data, nil } func GetGiteaSessionToken(ctx context.Context, auth BasicAuth, baseUrl string) (string, error) { httpClient := GetHttpClient() sessionEP := fmt.Sprintf("%s%s", baseUrl, fmt.Sprintf(GiteaSessionEndpoint, auth.Username)) sb := []byte(fmt.Sprintf(`{"name":"%d", "scopes":["%s"]}`, time.Now().Unix(), gitea.AccessTokenScopeAll)) sessionReq, err := http.NewRequestWithContext(ctx, http.MethodPost, sessionEP, bytes.NewBuffer(sb)) if err != nil { return "", fmt.Errorf("reating new request for session: %w", err) } sessionReq.SetBasicAuth(auth.Username, auth.Password) sessionReq.Header.Set("Content-Type", "application/json") var sess gitea.AccessToken err = SendAndParse(ctx, &sess, httpClient, sessionReq) if err != nil { return "", err } if sess.Token == "" { return "", fmt.Errorf("received empty token") } return sess.Token, nil } func TestArgoCDEndpoints(ctx context.Context, t *testing.T, baseUrl string) { t.Log("testing argocd endpoints") sessionURL := fmt.Sprintf("%s%s", baseUrl, ArgoCDSessionEndpoint) appURL := fmt.Sprintf("%s%s", baseUrl, ArgoCDAppsEndpoint) token, err := GetArgoCDSessionToken(ctx, sessionURL) assert.Nil(t, err, fmt.Sprintf("getting argocd token: %v", err)) httpClient := GetHttpClient() req, _ := http.NewRequestWithContext(ctx, http.MethodGet, appURL, nil) req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) var appResp ArgoCDAppResp err = SendAndParse(ctx, &appResp, httpClient, req) assert.Nil(t, err, fmt.Sprintf("getting argocd applications: %s", err)) assert.Equal(t, 3, len(appResp.Items), fmt.Sprintf("number of apps do not match: %v", appResp.Items)) } func GetBasicAuth(ctx context.Context, name string) (BasicAuth, error) { var lastErr error for attempt := 0; attempt < 5; attempt++ { select { case <-ctx.Done(): return BasicAuth{}, ctx.Err() default: b, err := RunCommand(ctx, fmt.Sprintf("%s get secrets -o json", IdpbuilderBinaryLocation), 10*time.Second) if err != nil { lastErr = err time.Sleep(httpRetryDelay) continue } out := BasicAuth{} secs := make([]types.Secret, 2) if err = json.Unmarshal(b, &secs); err != nil { lastErr = err time.Sleep(httpRetryDelay) continue } for _, sec := range secs { if sec.Name == name { out.Password = sec.Password out.Username = sec.Username break } } if out.Password == "" || out.Username == "" { time.Sleep(httpRetryDelay) continue } return out, nil } } return BasicAuth{}, fmt.Errorf("failed after 5 attempts: %w", lastErr) } func GetArgoCDSessionToken(ctx context.Context, endpoint string) (string, error) { auth, err := GetBasicAuth(ctx, "argocd-initial-admin-secret") if err != nil { return "", err } httpClient := GetHttpClient() authJ, err := json.Marshal(auth) if err != nil { return "", err } req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewBuffer(authJ)) if err != nil { return "", err } req.Header.Set("Content-Type", "application/json") var tokenResp ArgoCDAuthResponse err = SendAndParse(ctx, &tokenResp, httpClient, req) if err != nil { return "", err } if tokenResp.Token == "" { return "", fmt.Errorf("received token is empty") } return tokenResp.Token, nil } func TestArgoCDApps(ctx context.Context, t *testing.T, kubeClient client.Client, apps map[string]string) { done := false for !done { select { case <-ctx.Done(): return default: for k := range apps { ns := apps[k] t.Logf("checking argocd app %s in %s ns", k, ns) ready, argoErr := isArgoAppSyncedAndHealthy(ctx, kubeClient, k, ns) if argoErr != nil { t.Logf("error when checking ArgoCD app health: %s", argoErr) continue } if ready { t.Logf("app %s ready", k) delete(apps, k) } } if len(apps) != 0 { t.Logf("waiting for apps to be ready") time.Sleep(httpRetryDelay) continue } done = true t.Log("all argocd apps healthy") } } } func isArgoAppSyncedAndHealthy(ctx context.Context, kubeClient client.Client, name, namespace string) (bool, error) { app := argov1alpha1.Application{} err := kubeClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, &app) if err != nil { return false, err } return app.Status.Health.Status == "Healthy" && app.Status.Sync.Status == "Synced", nil } func GetKubeClient() (client.Client, error) { conf, err := clientcmd.BuildConfigFromFlags("", filepath.Join(homedir.HomeDir(), ".kube", "config")) if err != nil { return nil, err } return client.New(conf, client.Options{Scheme: k8s.GetScheme()}) } // login, build a test image, push, then pull. func TestGiteaRegistry(ctx context.Context, t *testing.T, cmd, giteaHost, giteaPort string) { t.Log("testing gitea container registry") b, err := RunCommand(ctx, fmt.Sprintf("%s get secrets -o json -p gitea", IdpbuilderBinaryLocation), 10*time.Second) assert.NoError(t, err) secs := make([]types.Secret, 1) err = json.Unmarshal(b, &secs) assert.NoError(t, err) sec := secs[0] user := sec.Username pass := sec.Password login, err := RunCommand(ctx, fmt.Sprintf("%s login %s:%s -u %s -p %s", cmd, giteaHost, giteaPort, user, pass), 10*time.Second) require.NoErrorf(t, err, "%s login err: %s", cmd, login) tag := fmt.Sprintf("%s:%s/giteaadmin/test:latest", giteaHost, giteaPort) build, err := RunCommand(ctx, fmt.Sprintf("%s build -f test-dockerfile -t %s .", cmd, tag), 10*time.Second) require.NoErrorf(t, err, "%s build err: %s", cmd, build) push, err := RunCommand(ctx, fmt.Sprintf("%s push %s", cmd, tag), 10*time.Second) require.NoErrorf(t, err, "%s push err: %s", cmd, push) pull, err := RunCommand(ctx, fmt.Sprintf("%s pull %s", cmd, tag), 10*time.Second) require.NoErrorf(t, err, "%s pull err: %s", cmd, pull) } // login, build a test image, push, then pull. func TestGiteaRegistryInCluster(ctx context.Context, t *testing.T, cmd, giteaHost, giteaPort string, kubeClient client.Client) { t.Log("testing using gitea container registry in cluster") b, err := RunCommand(ctx, fmt.Sprintf("%s get secrets -o json -p gitea", IdpbuilderBinaryLocation), 10*time.Second) assert.NoError(t, err) secs := make([]types.Secret, 1) err = json.Unmarshal(b, &secs) assert.NoError(t, err) sec := secs[0] user := sec.Username pass := sec.Password login, err := RunCommand(ctx, fmt.Sprintf("%s login %s:%s -u %s -p %s", cmd, giteaHost, giteaPort, user, pass), 10*time.Second) require.NoErrorf(t, err, "%s login err: %s", cmd, login) upstreamImage := "nginx" tag := fmt.Sprintf("%s:%s/giteaadmin/nginx:latest", giteaHost, giteaPort) pull, err := RunCommand(ctx, fmt.Sprintf("%s pull %s", cmd, upstreamImage), 10*time.Second) require.NoErrorf(t, err, "%s pull err: %s", cmd, pull) retag, err := RunCommand(ctx, fmt.Sprintf("%s tag %s %s", cmd, upstreamImage, tag), 10*time.Second) require.NoErrorf(t, err, "%s tag err: %s", cmd, retag) push, err := RunCommand(ctx, fmt.Sprintf("%s push %s", cmd, tag), 10*time.Second) require.NoErrorf(t, err, "%s push err: %s", cmd, push) pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "test-pod", Namespace: "default"}, Spec: corev1.PodSpec{ Containers: []corev1.Container{{ Name: "nginx", Image: tag, }}, }, } err = kubeClient.Create(ctx, pod) require.NoErrorf(t, err, "pod creation err") // Retry for 30 seconds backoff := wait.Backoff{ Steps: 3, Duration: 10 * time.Second, Jitter: 0.0, } retriable := func(_ error) bool { // Retry all errors return true } testfunc := func() error { foundPod := &corev1.Pod{} err = kubeClient.Get(ctx, client.ObjectKey{Name: pod.Name, Namespace: pod.Namespace}, foundPod) if err != nil { return err } if foundPod.Status.Phase != "Running" { return fmt.Errorf("Pod phase not running: %s", foundPod.Status.Phase) } return nil } err = retry.OnError(backoff, retriable, testfunc) require.NoErrorf(t, err, "pod startup err") }